OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [classpath/] [tools/] [gnu/] [classpath/] [tools/] [javah/] [Main.java] - Blame information for rev 779

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 779 jeremybenn
/* Main.java - javah main program
2
 Copyright (C) 2006, 2007 Free Software Foundation, Inc.
3
 
4
 This file is part of GNU Classpath.
5
 
6
 GNU Classpath is free software; you can redistribute it and/or modify
7
 it under the terms of the GNU General Public License as published by
8
 the Free Software Foundation; either version 2, or (at your option)
9
 any later version.
10
 
11
 GNU Classpath is distributed in the hope that it will be useful, but
12
 WITHOUT ANY WARRANTY; without even the implied warranty of
13
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 General Public License for more details.
15
 
16
 You should have received a copy of the GNU General Public License
17
 along with GNU Classpath; see the file COPYING.  If not, write to the
18
 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
 02110-1301 USA.
20
 
21
 Linking this library statically or dynamically with other modules is
22
 making a combined work based on this library.  Thus, the terms and
23
 conditions of the GNU General Public License cover the whole
24
 combination.
25
 
26
 As a special exception, the copyright holders of this library give you
27
 permission to link this library with independent modules to produce an
28
 executable, regardless of the license terms of these independent
29
 modules, and to copy and distribute the resulting executable under
30
 terms of your choice, provided that you also meet, for each linked
31
 independent module, the terms and conditions of the license of that
32
 module.  An independent module is a module which is not derived from
33
 or based on this library.  If you modify this library, you may extend
34
 this exception to your version of the library, but you are not
35
 obligated to do so.  If you do not wish to do so, delete this
36
 exception statement from your version. */
37
 
38
 
39
package gnu.classpath.tools.javah;
40
 
41
import gnu.classpath.tools.common.ClasspathToolParser;
42
import gnu.classpath.tools.getopt.Option;
43
import gnu.classpath.tools.getopt.OptionException;
44
import gnu.classpath.tools.getopt.Parser;
45
 
46
import java.io.BufferedReader;
47
import java.io.File;
48
import java.io.FileFilter;
49
import java.io.FileInputStream;
50
import java.io.FileNotFoundException;
51
import java.io.IOException;
52
import java.io.InputStream;
53
import java.io.InputStreamReader;
54
import java.net.URL;
55
import java.net.URLClassLoader;
56
import java.util.ArrayList;
57
import java.util.Arrays;
58
import java.util.HashMap;
59
import java.util.HashSet;
60
import java.util.Iterator;
61
import java.util.Map;
62
 
63
import org.objectweb.asm.ClassReader;
64
 
65
public class Main
66
{
67
  // This is an option group for classpath-related options,
68
  // and also is used for loading classes.
69
  PathOptionGroup classpath = new PathOptionGroup();
70
 
71
  // The output directory.
72
  String outputDir;
73
 
74
  // The output file name used if/when -o option is used.
75
  String outFileName;
76
 
77
  // The loader that we use to load class files.
78
  URLClassLoader loader;
79
 
80
  // In -all mode, the name of the directory to scan.
81
  String allDirectory;
82
 
83
  // True for verbose mode.
84
  boolean verbose;
85
 
86
  // True if we're emitting stubs.
87
  boolean stubs;
88
 
89
  // True if we're emitting CNI code.
90
  boolean cni;
91
 
92
  // True if we've seen -cni or -jni.
93
  boolean cniOrJniSeen;
94
 
95
  // True if output files should always be written.
96
  boolean force;
97
 
98
  // Map class names to class wrappers.
99
  HashMap<String,ClassWrapper> classMap = new HashMap<String,ClassWrapper>();
100
 
101
  // Map class names to lists of Text objects.
102
  HashMap<String,ArrayList<Text>> textMap = new HashMap<String,ArrayList<Text>>();
103
 
104
  void readCommandFile(String textFileName) throws OptionException
105
  {
106
    FileInputStream fis;
107
    try
108
      {
109
        fis = new FileInputStream(textFileName);
110
      }
111
    catch (FileNotFoundException ignore)
112
      {
113
        throw new OptionException("file \"" + textFileName + "\" not found");
114
      }
115
    BufferedReader reader = new BufferedReader(new InputStreamReader(fis));
116
    String currentClass = null;
117
    ArrayList<Text> currentValues = null;
118
    while (true)
119
      {
120
        String line;
121
        try
122
          {
123
            line = reader.readLine();
124
          }
125
        catch (IOException _)
126
          {
127
            break;
128
          }
129
        if (line == null)
130
          break;
131
        line = line.trim();
132
        if (line.length() == 0 || line.charAt(0) == '#')
133
          continue;
134
        int index = line.indexOf(' ');
135
        String cmd = line.substring(0, index);
136
        String value = line.substring(index + 1);
137
        int cmdValue;
138
        if ("class".equals(cmd))
139
          {
140
            if (currentClass != null)
141
              {
142
                textMap.put(currentClass, currentValues);
143
              }
144
            currentClass = value;
145
            currentValues = new ArrayList<Text>();
146
            continue;
147
          }
148
        if (currentClass == null)
149
          throw new OptionException("no class set");
150
        if ("add".equals(cmd))
151
          cmdValue = Text.ADD;
152
        else if ("append".equals(cmd))
153
          cmdValue = Text.APPEND;
154
        else if ("prepend".equals(cmd))
155
          cmdValue = Text.PREPEND;
156
        else if ("friend".equals(cmd))
157
          cmdValue = Text.FRIEND;
158
        else
159
          throw new OptionException("unrecognized command: " + cmd);
160
        currentValues.add(new Text(cmdValue, value));
161
      }
162
    if (currentClass != null)
163
      {
164
        textMap.put(currentClass, currentValues);
165
      }
166
  }
167
 
168
  void scanDirectory(File dir, final HashSet<Object> results)
169
  {
170
    File[] files = dir.listFiles(new FileFilter()
171
    {
172
      public boolean accept(File pathname)
173
      {
174
        if (pathname.isDirectory())
175
          {
176
            scanDirectory(pathname, results);
177
            return false;
178
          }
179
        return pathname.getName().endsWith(".class");
180
      }
181
    });
182
    if (files != null)
183
      results.addAll(Arrays.asList(files));
184
  }
185
 
186
  protected String getName()
187
  {
188
    return "javah";
189
  }
190
 
191
  protected ClasspathToolParser getParser()
192
  {
193
    ClasspathToolParser result = new ClasspathToolParser(getName(), true);
194
    result.setHeader("usage: javah [OPTIONS] CLASS...");
195
    result.add(classpath);
196
    result.add(new Option('d', "Set output directory", "DIR")
197
    {
198
      public void parsed(String dir) throws OptionException
199
      {
200
        if (outputDir != null)
201
          throw new OptionException("-d already seen");
202
        if (outFileName != null)
203
          throw new OptionException("only one of -d or -o may be used");
204
        outputDir = dir;
205
      }
206
    });
207
    result.add(new Option('o',
208
                          "Set output file (only one of -d or -o may be used)",
209
                          "FILE")
210
    {
211
      public void parsed(String fileName) throws OptionException
212
      {
213
        if (outFileName != null)
214
          throw new OptionException("-o already seen");
215
        if (outputDir != null)
216
          throw new OptionException("only one of -d or -o may be used");
217
        outFileName = fileName;
218
      }
219
    });
220
    result.add(new Option("cmdfile", "Read command file", "FILE")
221
    {
222
      public void parsed(String file) throws OptionException
223
      {
224
        readCommandFile(file);
225
      }
226
    });
227
    result.add(new Option("all", "Operate on all class files under directory",
228
                          "DIR")
229
    {
230
      public void parsed(String arg) throws OptionException
231
      {
232
        // FIXME: lame restriction...
233
        if (allDirectory != null)
234
          throw new OptionException("-all already specified");
235
        allDirectory = arg;
236
      }
237
    });
238
    result.add(new Option("stubs", "Emit stub implementation")
239
    {
240
      public void parsed(String arg0) throws OptionException
241
      {
242
        stubs = true;
243
      }
244
    });
245
    result.add(new Option("jni", "Emit JNI stubs or header (default)")
246
    {
247
      public void parsed(String arg0) throws OptionException
248
      {
249
        if (cniOrJniSeen && cni)
250
          throw new OptionException("only one of -jni or -cni may be used");
251
        cniOrJniSeen = true;
252
        cni = false;
253
      }
254
    });
255
    result.add(new Option("cni", "Emit CNI stubs or header (default JNI)")
256
    {
257
      public void parsed(String arg0) throws OptionException
258
      {
259
        if (cniOrJniSeen && ! cni)
260
          throw new OptionException("only one of -jni or -cni may be used");
261
        cniOrJniSeen = true;
262
        cni = true;
263
      }
264
    });
265
    result.add(new Option("verbose", 'v', "Set verbose mode")
266
    {
267
      public void parsed(String arg0) throws OptionException
268
      {
269
        verbose = true;
270
      }
271
    });
272
    result.add(new Option("force", "Output files should always be written")
273
    {
274
      public void parsed(String arg0) throws OptionException
275
      {
276
        force = true;
277
      }
278
    });
279
    return result;
280
  }
281
 
282
  private File makeOutputDirectory() throws IOException
283
  {
284
    File outputFile;
285
    if (outputDir == null)
286
      outputFile = new File(".");
287
    else
288
      outputFile = new File(outputDir);
289
    return outputFile;
290
  }
291
 
292
  /**
293
   * @return The {@link File} object where the generated code will be written.
294
   *         Returns <code>null</code> if the option <code>-force</code> was
295
   *         specified on the command line and the designated file already
296
   *         exists.
297
   * @throws IOException if <code>outFileName</code> is not a writable file.
298
   */
299
  private File makeOutputFile() throws IOException
300
  {
301
    File result = new File(outFileName);
302
    if (result.exists())
303
      {
304
        if (! result.isFile())
305
          throw new IOException("'" + outFileName + "' is not a file");
306
        if (! force)
307
          {
308
            if (verbose)
309
              System.err.println("["+ outFileName
310
                                 + " already exists.  Use -force to overwrite]");
311
            return null;
312
          }
313
        if (! result.delete())
314
          throw new IOException("Was unable to delete existing file: "
315
                                + outFileName);
316
      }
317
    return result;
318
  }
319
 
320
  private void writeHeaders(HashMap<File,ClassWrapper> klasses, Printer printer)
321
      throws IOException
322
  {
323
    Iterator<Map.Entry<File,ClassWrapper>> i = klasses.entrySet().iterator();
324
    while (i.hasNext())
325
      {
326
        Map.Entry<File,ClassWrapper> e = i.next();
327
        File file = e.getKey();
328
        ClassWrapper klass = e.getValue();
329
        if (verbose)
330
          System.err.println("[writing " + klass + " as " + file + "]");
331
        printer.printClass(file, klass);
332
      }
333
  }
334
 
335
  protected void postParse(String[] names)
336
  {
337
    // Nothing here.
338
  }
339
 
340
  protected void run(String[] args) throws IOException
341
  {
342
    ClasspathToolParser p = getParser();
343
    String[] classNames = p.parse(args, true);
344
    postParse(classNames);
345
    loader = classpath.getLoader();
346
 
347
    boolean isDirectory = outFileName == null;
348
    File outputFile = isDirectory ? makeOutputDirectory() : makeOutputFile();
349
    if (outputFile == null)
350
      return;
351
 
352
    Printer printer;
353
    if (! cni)
354
      {
355
        if (stubs)
356
          printer = new JniStubPrinter(this, outputFile, isDirectory, force);
357
        else
358
          printer = new JniIncludePrinter(this, outputFile, isDirectory, force);
359
      }
360
    else
361
      {
362
        if (stubs)
363
          printer = new CniStubPrinter(this, outputFile, isDirectory, force);
364
        else
365
          printer = new CniIncludePrinter(this, outputFile, isDirectory, force);
366
      }
367
 
368
    // First we load all of the files. That way if
369
    // there are references between the files we will
370
    // be loading the set that the user asked for.
371
    HashSet<Object> klasses = new HashSet<Object>();
372
    if (allDirectory != null)
373
      scanDirectory(new File(allDirectory), klasses);
374
    // Add the command-line arguments. We use the type of
375
    // an item in 'klasses' to decide how to load each class.
376
    for (int i = 0; i < classNames.length; ++i)
377
      {
378
        if (classNames[i].endsWith(".class"))
379
          {
380
            klasses.add(new File(classNames[i]));
381
          }
382
        else
383
          {
384
            klasses.add(classNames[i]);
385
          }
386
      }
387
 
388
    Iterator<Object> i = klasses.iterator();
389
    HashMap<File,ClassWrapper> results = new HashMap<File,ClassWrapper>();
390
    while (i.hasNext())
391
      {
392
        // Let user specify either kind of class name or a
393
        // file name.
394
        Object item = i.next();
395
        ClassWrapper klass;
396
        File filename;
397
        if (item instanceof File)
398
          {
399
            // Load class from file.
400
            if (verbose)
401
              System.err.println("[reading file " + item + "]");
402
            klass = getClass((File) item);
403
            filename = new File(klass.name);
404
          }
405
        else
406
          {
407
            // Load class given the class name.
408
            String className = ((String) item).replace('.', '/');
409
            if (verbose)
410
              System.err.println("[reading class " + className + "]");
411
            // Use the name the user specified, even if it is
412
            // different from the ultimate class name.
413
            filename = new File(className);
414
            klass = getClass(className);
415
          }
416
        results.put(filename, klass);
417
      }
418
 
419
    writeHeaders(results, printer);
420
  }
421
 
422
  public ArrayList<Text> getClassTextList(String name)
423
  {
424
    return textMap.get(name);
425
  }
426
 
427
  private ClassWrapper readClass(InputStream is) throws IOException
428
  {
429
    ClassReader r = new ClassReader(is);
430
    ClassWrapper result = new ClassWrapper(this);
431
    r.accept(result, true);
432
    is.close();
433
    return result;
434
  }
435
 
436
  private ClassWrapper getClass(File fileName) throws IOException
437
  {
438
    InputStream is = new FileInputStream(fileName);
439
    ClassWrapper result = readClass(is);
440
    if (classMap.containsKey(result.name))
441
      throw new IllegalArgumentException("class " + result.name
442
                                         + " already loaded");
443
    classMap.put(result.name, result);
444
    return result;
445
  }
446
 
447
  public ClassWrapper getClass(String name) throws IOException
448
  {
449
    if (! classMap.containsKey(name))
450
      {
451
        String resource = name.replace('.', '/') + ".class";
452
        URL url = loader.findResource(resource);
453
        if (url == null)
454
          throw new IOException("can't find class file " + resource
455
                                + " in " + loader);
456
        InputStream is = url.openStream();
457
        ClassWrapper result = readClass(is);
458
        classMap.put(name, result);
459
      }
460
    return (ClassWrapper) classMap.get(name);
461
  }
462
 
463
  public static void main(String[] args) throws IOException
464
  {
465
    Main m = new Main();
466
    m.run(args);
467
  }
468
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.