]> gcc.gnu.org Git - gcc.git/blame - gcc/java/gjavah.c
i386.md (*sinxf2): Rename to *sinxf2_i387.
[gcc.git] / gcc / java / gjavah.c
CommitLineData
e04a16fb
AG
1/* Program to write C++-suitable header files from a Java(TM) .class
2 file. This is similar to SUN's javah.
3
a6d6c2c0 4Copyright (C) 1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
f309ff0a 5Free Software Foundation, Inc.
e04a16fb 6
f309ff0a
SB
7This file is part of GCC.
8
9GCC is free software; you can redistribute it and/or modify
e04a16fb
AG
10it under the terms of the GNU General Public License as published by
11the Free Software Foundation; either version 2, or (at your option)
12any later version.
13
f309ff0a 14GCC is distributed in the hope that it will be useful,
e04a16fb
AG
15but WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17GNU General Public License for more details.
18
19You should have received a copy of the GNU General Public License
f309ff0a 20along with GCC; see the file COPYING. If not, write to
f12c30a8
KC
21the Free Software Foundation, 51 Franklin Street, Fifth Floor,
22Boston, MA 02110-1301, USA.
e04a16fb
AG
23
24Java and all Java-based marks are trademarks or registered trademarks
25of Sun Microsystems, Inc. in the United States and other countries.
26The Free Software Foundation is independent of Sun Microsystems, Inc. */
27
28/* Written by Per Bothner <bothner@cygnus.com>, February 1996. */
29
9caaf519
KG
30#include "config.h"
31#include "system.h"
4977bab6
ZW
32#include "coretypes.h"
33#include "tm.h"
4f65832d
KG
34#include <math.h>
35
e04a16fb 36#include "jcf.h"
4f65832d 37#include "tree.h"
a757585a 38#include "version.h"
9b4a08f9 39#include "javaop.h"
4f65832d 40#include "java-tree.h"
92c068d1 41#include "java-opcodes.h"
17211ab5 42#include "ggc.h"
6b9b5de2 43#include "hashtab.h"
0237b2dc 44#include "intl.h"
92c068d1 45
c89c53eb
TT
46#include <getopt.h>
47
48\f
49
e04a16fb
AG
50/* The output file. */
51FILE *out = NULL;
52
53/* Nonzero on failure. */
54static int found_error = 0;
55
d8be0aab
TF
56#ifdef JNI_DEFAULT
57#define TOOLNAME "gjnih"
58
de380723 59/* Nonzero if we're generating JNI output. */
d8be0aab
TF
60int flag_jni = 1;
61#else
62#define TOOLNAME "gcjh"
63
a6d682a0 64int flag_jni = 0;
d8be0aab 65#endif
de380723 66
ee142fe7 67/* When nonzero, warn when source file is newer than matching class
b7436b72
TT
68 file. */
69int flag_newer = 1;
70
e04a16fb 71/* Directory to place resulting files in. Set by -d option. */
82698cde 72static const char *output_directory = "";
e04a16fb 73
e04a16fb 74/* Directory to place temporary file. Set by -td option. Currently unused. */
82698cde 75static const char *temp_directory = "/tmp";
e04a16fb
AG
76
77/* Number of friend functions we have to declare. */
78static int friend_count;
79
80/* A class can optionally have a `friend' function declared. If
81 non-NULL, this is that function. */
82static char **friend_specs = NULL;
83
84/* Number of lines we are prepending before the class. */
85static int prepend_count;
86
87/* We can prepend extra lines before the class's start. */
88static char **prepend_specs = NULL;
89
90/* Number of lines we are appending at the end of the class. */
91static int add_count;
92
93/* We can append extra lines just before the class's end. */
94static char **add_specs = NULL;
95
96/* Number of lines we are appending after the class. */
97static int append_count;
98
99/* We can append extra lines after the class's end. */
100static char **append_specs = NULL;
101
102int verbose = 0;
103
104int stubs = 0;
105
106struct JCF *current_jcf;
e04a16fb
AG
107
108/* This holds access information for the last field we examined. They
109 let us generate "private:", "public:", and "protected:" properly.
110 If 0 then we haven't previously examined any field. */
111static JCF_u2 last_access;
112
bdb59aec
TT
113/* Pass this macro the flags for a class and for a method. It will
114 return true if the method should be considered `final'. */
115#define METHOD_IS_FINAL(Class, Method) \
116 (((Class) & ACC_FINAL) || ((Method) & (ACC_FINAL | ACC_PRIVATE)))
117
6c9c5c1f
AG
118/* Pass this macro the flags for a method. It will return true if the
119 method is native. */
120#define METHOD_IS_NATIVE(Method) \
121 ((Method) & ACC_NATIVE)
122
36739040
TT
123#define METHOD_IS_PRIVATE(Class, Method) \
124 (((Method) & ACC_PRIVATE) != 0)
125
e4de5a10
PB
126/* We keep a linked list of all method names we have seen. This lets
127 us determine if a method name and a field name are in conflict. */
128struct method_name
129{
130 unsigned char *name;
131 int length;
de380723
TT
132 unsigned char *signature;
133 int sig_length;
3fb577a5 134 int is_native;
e4de5a10
PB
135 struct method_name *next;
136};
137
138/* List of method names we've seen. */
139static struct method_name *method_name_list;
e04a16fb 140
d2097937
KG
141static void print_field_info (FILE*, JCF*, int, int, JCF_u2);
142static void print_mangled_classname (FILE*, JCF*, const char*, int);
143static int print_cxx_classname (FILE*, const char*, JCF*, int, int);
144static void print_method_info (FILE*, JCF*, int, int, JCF_u2);
145static void print_c_decl (FILE*, JCF*, int, int, int, const char *, int);
146static void print_stub_or_jni (FILE*, JCF*, int, int, int, const char *, int);
147static void print_full_cxx_name (FILE*, JCF*, int, int, int, const char *, int);
e263bc93 148static void decompile_method (FILE*, JCF*, int) ATTRIBUTE_UNUSED;
d2097937
KG
149static void add_class_decl (FILE*, JCF*, JCF_u2);
150
d2097937
KG
151static void print_name (FILE *, JCF *, int);
152static void print_base_classname (FILE *, JCF *, int);
153static int utf8_cmp (const unsigned char *, int, const char *);
154static char *cxx_keyword_subst (const unsigned char *, int);
155static void generate_access (FILE *, JCF_u2);
156static int name_is_method_p (const unsigned char *, int);
157static char *get_field_name (JCF *, int, JCF_u2);
158static void print_field_name (FILE *, JCF *, int, JCF_u2);
159static const unsigned char *super_class_name (JCF *, int *);
160static void print_include (FILE *, const unsigned char *, int);
161static int gcjh_streq (const void *p1, const void *p2);
162static int throwable_p (const unsigned char *signature);
163static const unsigned char *
164 decode_signature_piece (FILE *, const unsigned char *,
165 const unsigned char *, int *);
166static void print_class_decls (FILE *, JCF *, int);
74118f15 167static void error (const char *gmsgid, ...) ATTRIBUTE_PRINTF_1;
d2097937
KG
168static void usage (void) ATTRIBUTE_NORETURN;
169static void help (void) ATTRIBUTE_NORETURN;
170static void version (void) ATTRIBUTE_NORETURN;
171static int overloaded_jni_method_exists_p (const unsigned char *, int,
172 const char *, int);
173static void jni_print_char (FILE *, int);
649eaf9b
ZW
174static void jni_print_float (FILE *, jfloat);
175static void jni_print_double (FILE *, jdouble);
d2097937 176static void decompile_return_statement (FILE *, JCF *, int, int, int);
08967681 177
73cb3b5a
TT
178static void handle_inner_classes (int);
179
e04a16fb
AG
180JCF_u2 current_field_name;
181JCF_u2 current_field_value;
182JCF_u2 current_field_signature;
183JCF_u2 current_field_flags;
184
185#define HANDLE_START_FIELD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \
186( current_field_name = (NAME), current_field_signature = (SIGNATURE), \
187 current_field_flags = (ACCESS_FLAGS), current_field_value = 0)
188
bdb59aec
TT
189/* We pass over fields twice. The first time we just note the types
190 of the fields and then the start of the methods. Then we go back
191 and parse the fields for real. This is ugly. */
e4de5a10 192static int field_pass;
bdb59aec
TT
193/* Likewise we pass over methods twice. The first time we generate
194 class decl information; the second time we generate actual method
195 decls. */
196static int method_pass;
197
198#define HANDLE_END_FIELD() \
199 if (field_pass) \
200 { \
5e74a4eb 201 if (out && ! stubs) \
bdb59aec
TT
202 print_field_info (out, jcf, current_field_name, \
203 current_field_signature, \
c89c53eb 204 current_field_flags); \
bdb59aec 205 } \
de380723
TT
206 else if (! stubs && ! flag_jni) \
207 add_class_decl (out, jcf, current_field_signature);
e04a16fb
AG
208
209#define HANDLE_CONSTANTVALUE(VALUEINDEX) current_field_value = (VALUEINDEX)
210
8c2dfb32 211static int method_declared = 0;
cb975f38 212static int method_access = 0;
bdb59aec 213static int method_printed = 0;
f0f3a777 214static int method_synthetic = 0;
150f086d
TT
215static int method_signature = 0;
216
68566610
AH
217/* Set to 1 while the very first data member of a class is being handled. */
218static int is_first_data_member = 0;
219
f0f3a777
APB
220#define HANDLE_METHOD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \
221 { \
222 method_synthetic = 0; \
4440ffc4 223 method_printed = 0; \
897c9e66 224 decompiled = 0; \
150f086d 225 method_signature = SIGNATURE; \
f0f3a777
APB
226 if (ATTRIBUTE_COUNT) \
227 method_synthetic = peek_attribute (jcf, ATTRIBUTE_COUNT, \
228 (const char *)"Synthetic", 9); \
229 /* If a synthetic methods have been declared, its attribute aren't \
230 worth reading (and triggering side-effects). We skip them an \
231 set ATTRIBUTE_COUNT to zero so that they'll be skipped in \
232 jcf_parse_one_method. */ \
233 if (method_synthetic) \
234 { \
235 skip_attribute (jcf, ATTRIBUTE_COUNT); \
236 ATTRIBUTE_COUNT = 0; \
237 } \
238 if (method_pass && !method_synthetic) \
239 { \
f0f3a777
APB
240 if (out) \
241 print_method_info (out, jcf, NAME, SIGNATURE, \
150f086d 242 ACCESS_FLAGS); \
f0f3a777
APB
243 } \
244 else if (!method_synthetic) \
245 { \
246 print_method_info (NULL, jcf, NAME, SIGNATURE, \
150f086d 247 ACCESS_FLAGS); \
f0f3a777
APB
248 if (! stubs && ! flag_jni) \
249 add_class_decl (out, jcf, SIGNATURE); \
250 } \
251 }
252
e263bc93
TL
253/* Only include byte-code decompilation optimizations for ELF targets
254 since the generated headers are only known to work with ELF weak
f48c58e8 255 symbol semantics. Specifically, these optimizations are known to
e263bc93
TL
256 not work on PE-COFF and possibly others. */
257#ifdef OBJECT_FORMAT_ELF
f0f3a777 258#define HANDLE_CODE_ATTRIBUTE(MAX_STACK, MAX_LOCALS, CODE_LENGTH) \
8c2dfb32 259 if (out && method_declared) decompile_method (out, jcf, CODE_LENGTH);
e263bc93 260#endif
92c068d1
TT
261
262static int decompiled = 0;
f0f3a777
APB
263#define HANDLE_END_METHOD() \
264 if (out && method_printed && !method_synthetic) \
265 fputs (decompiled || stubs ? "\n" : ";\n", out);
e04a16fb 266
73cb3b5a
TT
267#define HANDLE_INNERCLASSES_ATTRIBUTE(COUNT) handle_inner_classes (COUNT)
268
80393943
KG
269/* We're going to need {peek,skip}_attribute, enable their definition. */
270#define NEED_PEEK_ATTRIBUTE
271#define NEED_SKIP_ATTRIBUTE
272
e04a16fb
AG
273#include "jcf-reader.c"
274
4b794eaf
JJ
275/* Print an error message and set found_error.
276 Not really gcc-internal-format message, but as error elsewhere
277 uses it, assume all users will use intersection between
278 c-format and gcc-internal-format. */
0237b2dc 279static void
4b794eaf 280error (const char *gmsgid, ...)
0237b2dc
JM
281{
282 va_list ap;
283
4b794eaf 284 va_start (ap, gmsgid);
0237b2dc 285
d8be0aab 286 fprintf (stderr, TOOLNAME ": ");
4b794eaf 287 vfprintf (stderr, _(gmsgid), ap);
0237b2dc
JM
288 va_end (ap);
289 fprintf (stderr, "\n");
290 found_error = 1;
291}
292
649eaf9b
ZW
293/* Print a single-precision float, suitable for parsing by g++. */
294static void
295jni_print_float (FILE *stream, jfloat f)
e04a16fb 296{
649eaf9b
ZW
297 /* It'd be nice to use __builtin_nan/__builtin_inf here but they don't
298 work in data initializers. FIXME. */
299 if (JFLOAT_FINITE (f))
300 {
f619dcab
RM
301 if (flag_jni)
302 {
303 fputs (" ", out);
304 if (f.negative)
305 putc ('-', stream);
306 if (f.exponent)
307 fprintf (stream, "0x1.%.6xp%+df",
308 ((unsigned int)f.mantissa) << 1,
309 f.exponent - JFLOAT_EXP_BIAS);
310 else
311 /* Exponent of 0x01 is -125; exponent of 0x00 is *also* -125,
312 because the implicit leading 1 bit is no longer present. */
313 fprintf (stream, "0x0.%.6xp%+df",
314 ((unsigned int)f.mantissa) << 1,
315 f.exponent + 1 - JFLOAT_EXP_BIAS);
316 }
649eaf9b 317 }
5e74a4eb
TT
318 if (! flag_jni)
319 fputs (";\n", stream);
e04a16fb
AG
320}
321
649eaf9b
ZW
322/* Print a double-precision float, suitable for parsing by g++. */
323static void
324jni_print_double (FILE *stream, jdouble f)
e04a16fb 325{
649eaf9b
ZW
326 /* It'd be nice to use __builtin_nan/__builtin_inf here but they don't
327 work in data initializers. FIXME. */
328 if (JDOUBLE_FINITE (f))
329 {
f619dcab
RM
330 if (flag_jni)
331 {
332 fputs (" ", out);
333 if (f.negative)
334 putc ('-', stream);
335 if (f.exponent)
336 fprintf (stream, "0x1.%.5x%.8xp%+d",
337 f.mantissa0, f.mantissa1,
338 f.exponent - JDOUBLE_EXP_BIAS);
339 else
340 /* Exponent of 0x001 is -1022; exponent of 0x000 is *also* -1022,
341 because the implicit leading 1 bit is no longer present. */
342 fprintf (stream, "0x0.%.5x%.8xp%+d",
343 f.mantissa0, f.mantissa1,
344 f.exponent + 1 - JDOUBLE_EXP_BIAS);
345 }
649eaf9b 346 }
5e74a4eb 347 fputs (flag_jni ? "\n" : ";\n", stream);
e04a16fb
AG
348}
349
78de74be
TT
350/* Print a character, appropriately mangled for JNI. */
351
352static void
0a2f0c54 353jni_print_char (FILE *stream, int ch)
78de74be
TT
354{
355 if (! flag_jni)
356 jcf_print_char (stream, ch);
357 else if (ch == '(' || ch == ')')
358 {
359 /* Ignore. */
360 }
361 else if (ch == '_')
362 fputs ("_1", stream);
363 else if (ch == ';')
364 fputs ("_2", stream);
365 else if (ch == '[')
366 fputs ("_3", stream);
367 else if (ch == '/')
368 fputs ("_", stream);
299b5f9e 369 else if (ISALNUM (ch))
78de74be
TT
370 fputc (ch, stream);
371 else
372 {
373 /* "Unicode" character. */
374 fprintf (stream, "_0%04x", ch);
375 }
376}
377
c45c5e09
TT
378/* Print a name from the class data. If the index does not point to a
379 string, an error results. */
380
381static void
6ff2fe39 382print_name (FILE* stream, JCF* jcf, int name_index)
c45c5e09
TT
383{
384 if (JPOOL_TAG (jcf, name_index) != CONSTANT_Utf8)
385 {
386 fprintf (stream, "<not a UTF8 constant>");
387 found_error = 1;
388 }
389 else if (! flag_jni)
390 jcf_print_utf8 (stream, JPOOL_UTF_DATA (jcf, name_index),
391 JPOOL_UTF_LENGTH (jcf, name_index));
392 else
393 {
394 /* For JNI we must correctly quote each character. */
395 const unsigned char *str = JPOOL_UTF_DATA (jcf, name_index);
396 int length = JPOOL_UTF_LENGTH (jcf, name_index);
397 const unsigned char *limit = str + length;
398 while (str < limit)
399 {
400 int ch = UTF8_GET (str, limit);
401 if (ch < 0)
402 {
403 fprintf (stream, "\\<invalid>");
404 return;
405 }
406 jni_print_char (stream, ch);
407 }
408 }
409}
410
e04a16fb
AG
411/* Print base name of class. The base name is everything after the
412 final separator. */
413
414static void
0a2f0c54 415print_base_classname (FILE *stream, JCF *jcf, int index)
e04a16fb
AG
416{
417 int name_index = JPOOL_USHORT1 (jcf, index);
fc45c7ef 418 int len;
be245ac0 419 const unsigned char *s, *p, *limit;
e04a16fb
AG
420
421 s = JPOOL_UTF_DATA (jcf, name_index);
422 len = JPOOL_UTF_LENGTH (jcf, name_index);
423 limit = s + len;
424 p = s;
425 while (s < limit)
426 {
427 int c = UTF8_GET (s, limit);
428 if (c == '/')
429 p = s;
430 }
431
432 while (p < limit)
433 {
434 int ch = UTF8_GET (p, limit);
435 if (ch == '/')
436 fputs ("::", stream);
437 else
438 jcf_print_char (stream, ch);
439 }
440}
441
83c1f628
TT
442/* Return 0 if NAME is equal to STR, -1 if STR is "less" than NAME,
443 and 1 if STR is "greater" than NAME. */
e04a16fb
AG
444
445static int
0a2f0c54 446utf8_cmp (const unsigned char *str, int length, const char *name)
e04a16fb 447{
be245ac0 448 const unsigned char *limit = str + length;
e04a16fb
AG
449 int i;
450
451 for (i = 0; name[i]; ++i)
452 {
453 int ch = UTF8_GET (str, limit);
454 if (ch != name[i])
83c1f628 455 return ch - name[i];
e04a16fb
AG
456 }
457
83c1f628 458 return str == limit ? 0 : 1;
e04a16fb
AG
459}
460
83c1f628
TT
461/* This is a sorted list of all C++ keywords. */
462
fd033052 463static const char *const cxx_keywords[] =
83c1f628 464{
f2a29271
BM
465 "_Complex",
466 "__alignof",
467 "__alignof__",
468 "__asm",
469 "__asm__",
470 "__attribute",
471 "__attribute__",
472 "__builtin_va_arg",
473 "__complex",
474 "__complex__",
475 "__const",
476 "__const__",
477 "__extension__",
478 "__imag",
479 "__imag__",
480 "__inline",
481 "__inline__",
482 "__label__",
483 "__null",
484 "__real",
485 "__real__",
486 "__restrict",
487 "__restrict__",
488 "__signed",
489 "__signed__",
490 "__typeof",
491 "__typeof__",
492 "__volatile",
493 "__volatile__",
f2a29271
BM
494 "and",
495 "and_eq",
7b35f6c9 496 "asm",
83c1f628 497 "auto",
f2a29271
BM
498 "bitand",
499 "bitor",
83c1f628 500 "bool",
f2a29271
BM
501 "break",
502 "case",
503 "catch",
504 "char",
505 "class",
506 "compl",
507 "const",
83c1f628 508 "const_cast",
f2a29271
BM
509 "continue",
510 "default",
83c1f628 511 "delete",
f2a29271
BM
512 "do",
513 "double",
83c1f628 514 "dynamic_cast",
f2a29271 515 "else",
83c1f628
TT
516 "enum",
517 "explicit",
f2a29271 518 "export",
83c1f628 519 "extern",
f2a29271
BM
520 "false",
521 "float",
522 "for",
83c1f628 523 "friend",
f2a29271
BM
524 "goto",
525 "if",
83c1f628 526 "inline",
f2a29271
BM
527 "int",
528 "long",
83c1f628
TT
529 "mutable",
530 "namespace",
f2a29271
BM
531 "new",
532 "not",
533 "not_eq",
534 "operator",
535 "or",
536 "or_eq",
537 "private",
538 "protected",
539 "public",
83c1f628
TT
540 "register",
541 "reinterpret_cast",
f2a29271
BM
542 "return",
543 "short",
83c1f628
TT
544 "signed",
545 "sizeof",
f2a29271 546 "static",
83c1f628
TT
547 "static_cast",
548 "struct",
f2a29271 549 "switch",
83c1f628 550 "template",
f2a29271
BM
551 "this",
552 "throw",
553 "true",
554 "try",
83c1f628 555 "typedef",
f2a29271 556 "typeid",
7b35f6c9 557 "typename",
f2a29271 558 "typeof",
83c1f628
TT
559 "union",
560 "unsigned",
561 "using",
562 "virtual",
f2a29271 563 "void",
83c1f628 564 "volatile",
f2a29271
BM
565 "wchar_t",
566 "while",
567 "xor",
568 "xor_eq"
83c1f628
TT
569};
570
571
5877286e
TT
572/* If NAME is the name of a C++ keyword, then return an override name.
573 This is a name that can be used in place of the keyword.
83c1f628 574 Otherwise, return NULL. The return value is malloc()d. */
5877286e 575
83c1f628 576static char *
0a2f0c54 577cxx_keyword_subst (const unsigned char *str, int length)
5877286e 578{
94574545 579 int last = ARRAY_SIZE (cxx_keywords);
83c1f628 580 int first = 0;
ecb36604
TT
581 int mid = (last + first) / 2;
582 int old = -1;
83c1f628 583
ecb36604
TT
584 for (mid = (last + first) / 2;
585 mid != old;
586 old = mid, mid = (last + first) / 2)
83c1f628 587 {
0160fbe1
TT
588 int kwl = strlen (cxx_keywords[mid]);
589 int min_length = kwl > length ? length : kwl;
590 int r = utf8_cmp (str, min_length, cxx_keywords[mid]);
ecb36604 591
83c1f628
TT
592 if (r == 0)
593 {
0160fbe1
TT
594 int i;
595
596 /* Skip all trailing `$'. */
597 for (i = min_length; i < length && str[i] == '$'; ++i)
598 ;
599 /* We've only found a match if all the remaining characters
600 are `$'. */
601 if (i == length)
602 {
5ed6ace5 603 char *dup = XNEWVEC (char, 2 + length - min_length + kwl);
0160fbe1
TT
604 strcpy (dup, cxx_keywords[mid]);
605 for (i = kwl; i < length + 1; ++i)
606 dup[i] = '$';
607 dup[i] = '\0';
608 return dup;
609 }
610 r = 1;
83c1f628 611 }
0160fbe1
TT
612
613 if (r < 0)
83c1f628
TT
614 last = mid;
615 else
616 first = mid;
617 }
5877286e
TT
618 return NULL;
619}
620
de380723 621/* Generate an access control keyword based on FLAGS. */
e04a16fb
AG
622
623static void
0a2f0c54 624generate_access (FILE *stream, JCF_u2 flags)
e04a16fb 625{
e04a16fb
AG
626 if ((flags & ACC_VISIBILITY) == last_access)
627 return;
628 last_access = (flags & ACC_VISIBILITY);
629
630 switch (last_access)
631 {
3217b0f3
PB
632 case 0:
633 fputs ("public: // actually package-private\n", stream);
634 break;
e04a16fb
AG
635 case ACC_PUBLIC:
636 fputs ("public:\n", stream);
637 break;
638 case ACC_PRIVATE:
639 fputs ("private:\n", stream);
640 break;
641 case ACC_PROTECTED:
3217b0f3 642 fputs ("public: // actually protected\n", stream);
e04a16fb
AG
643 break;
644 default:
645 found_error = 1;
646 fprintf (stream, "#error unrecognized visibility %d\n",
647 (flags & ACC_VISIBILITY));
648 break;
649 }
650}
651
e4de5a10
PB
652/* See if NAME is already the name of a method. */
653static int
0a2f0c54 654name_is_method_p (const unsigned char *name, int length)
e4de5a10
PB
655{
656 struct method_name *p;
657
658 for (p = method_name_list; p != NULL; p = p->next)
659 {
660 if (p->length == length && ! memcmp (p->name, name, length))
661 return 1;
662 }
663 return 0;
664}
665
b8b639c9
TT
666/* Free the method name list. */
667static void
e72222ac 668free_method_name_list (void)
b8b639c9
TT
669{
670 struct method_name *p = method_name_list;
671 while (p != NULL)
672 {
673 struct method_name *next = p->next;
674 free (p->name);
675 free (p->signature);
676 free (p);
677 p = next;
678 }
679 method_name_list = NULL;
680}
681
3fb577a5 682/* If there is already a native method named NAME, whose signature is not
de380723
TT
683 SIGNATURE, then return true. Otherwise return false. */
684static int
0a2f0c54
KG
685overloaded_jni_method_exists_p (const unsigned char *name, int length,
686 const char *signature, int sig_length)
de380723
TT
687{
688 struct method_name *p;
689
690 for (p = method_name_list; p != NULL; p = p->next)
691 {
3fb577a5
RM
692 if (p->is_native
693 && p->length == length
de380723
TT
694 && ! memcmp (p->name, name, length)
695 && (p->sig_length != sig_length
696 || memcmp (p->signature, signature, sig_length)))
697 return 1;
698 }
699 return 0;
700}
701
5877286e
TT
702/* Get name of a field. This handles renamings due to C++ clash. */
703static char *
0a2f0c54 704get_field_name (JCF *jcf, int name_index, JCF_u2 flags)
5877286e
TT
705{
706 unsigned char *name = JPOOL_UTF_DATA (jcf, name_index);
707 int length = JPOOL_UTF_LENGTH (jcf, name_index);
708 char *override;
be245ac0 709
5877286e
TT
710 if (name_is_method_p (name, length))
711 {
712 /* This field name matches a method. So override the name with
713 a dummy name. This is yucky, but it isn't clear what else to
714 do. FIXME: if the field is static, then we'll be in real
715 trouble. */
716 if ((flags & ACC_STATIC))
717 {
0237b2dc 718 error ("static field has same name as method");
5877286e
TT
719 return NULL;
720 }
721
5ed6ace5 722 override = XNEWVEC (char, length + 3);
5877286e
TT
723 memcpy (override, name, length);
724 strcpy (override + length, "__");
725 }
3d4da704
TT
726 else if (flag_jni)
727 override = NULL;
be245ac0 728 else
83c1f628
TT
729 override = cxx_keyword_subst (name, length);
730
5877286e
TT
731 return override;
732}
733
734/* Print a field name. Convenience function for use with
735 get_field_name. */
736static void
0a2f0c54 737print_field_name (FILE *stream, JCF *jcf, int name_index, JCF_u2 flags)
5877286e
TT
738{
739 char *override = get_field_name (jcf, name_index, flags);
740
741 if (override)
742 {
743 fputs (override, stream);
744 free (override);
745 }
746 else
747 jcf_print_utf8 (stream, JPOOL_UTF_DATA (jcf, name_index),
748 JPOOL_UTF_LENGTH (jcf, name_index));
749}
750
e04a16fb 751static void
6ff2fe39
KG
752print_field_info (FILE *stream, JCF* jcf, int name_index, int sig_index,
753 JCF_u2 flags)
e04a16fb 754{
e4de5a10
PB
755 char *override = NULL;
756
5e74a4eb
TT
757 if (! flag_jni)
758 generate_access (stream, flags);
5877286e
TT
759 if (JPOOL_TAG (jcf, name_index) != CONSTANT_Utf8)
760 {
761 fprintf (stream, "<not a UTF8 constant>");
762 found_error = 1;
763 return;
764 }
765
5e74a4eb
TT
766 if (flag_jni)
767 {
768 /* For JNI we only want to print real constants. */
769 int val;
770 if (! (flags & ACC_STATIC)
771 || ! (flags & ACC_FINAL)
772 || current_field_value <= 0)
773 return;
774 val = JPOOL_TAG (jcf, current_field_value);
775 if (val != CONSTANT_Integer && val != CONSTANT_Long
776 && val != CONSTANT_Float && val != CONSTANT_Double)
777 return;
778 }
779 else
780 {
781 /* Initial indentation. */
782 fputs (" ", stream);
783 }
784
9b4579b3 785 if ((flags & ACC_STATIC))
e04a16fb 786 {
5e74a4eb
TT
787 if (flag_jni)
788 {
789 print_cxx_classname (stream, "#undef ", jcf, jcf->this_class, 1);
790 fputs ("_", stream);
791 print_field_name (stream, jcf, name_index, 0);
792 fputs ("\n", stream);
793 print_cxx_classname (stream, "#define ", jcf, jcf->this_class, 1);
794 fputs ("_", stream);
795 }
22f8a068
MM
796 else
797 fputs ("static ", stream);
dd4e1500
BM
798
799 if ((flags & ACC_FINAL) && current_field_value > 0)
e04a16fb 800 {
e04a16fb 801 char buffer[25];
5877286e 802 int done = 1;
e04a16fb 803
e04a16fb
AG
804 switch (JPOOL_TAG (jcf, current_field_value))
805 {
806 case CONSTANT_Integer:
11b89622
TT
807 {
808 jint num;
06d84d69 809 int most_negative = 0;
5e74a4eb 810 if (! flag_jni)
22f8a068 811 fputs ("const jint ", stream);
5e74a4eb
TT
812 print_field_name (stream, jcf, name_index, 0);
813 fputs (flag_jni ? " " : " = ", stream);
11b89622 814 num = JPOOL_INT (jcf, current_field_value);
06d84d69
TT
815 /* We single out the most negative number to print
816 specially. This avoids later warnings from g++. */
7e21fe59 817 if (num == (jint) 0x80000000)
11b89622 818 {
06d84d69
TT
819 most_negative = 1;
820 ++num;
11b89622 821 }
06d84d69 822 format_int (buffer, (jlong) num, 10);
5e74a4eb
TT
823 fprintf (stream, "%sL%s%s\n", buffer,
824 most_negative ? " - 1" : "",
825 flag_jni ? "" : ";");
11b89622 826 }
e04a16fb
AG
827 break;
828 case CONSTANT_Long:
11b89622
TT
829 {
830 jlong num;
06d84d69 831 int most_negative = 0;
5e74a4eb 832 if (! flag_jni)
22f8a068 833 fputs ("const jlong ", stream);
5e74a4eb
TT
834 print_field_name (stream, jcf, name_index, 0);
835 fputs (flag_jni ? " " : " = ", stream);
11b89622 836 num = JPOOL_LONG (jcf, current_field_value);
06d84d69
TT
837 /* We single out the most negative number to print
838 specially.. This avoids later warnings from g++. */
7e21fe59 839 if (num == (jlong) 0x8000000000000000LL)
11b89622 840 {
06d84d69
TT
841 most_negative = 1;
842 ++num;
11b89622 843 }
06d84d69 844 format_int (buffer, num, 10);
5e74a4eb
TT
845 fprintf (stream, "%sLL%s%s\n", buffer,
846 most_negative ? " - 1" :"",
847 flag_jni ? "" : ";");
11b89622 848 }
e04a16fb
AG
849 break;
850 case CONSTANT_Float:
851 {
852 jfloat fnum = JPOOL_FLOAT (jcf, current_field_value);
5e74a4eb 853 if (! flag_jni)
22f8a068 854 fputs ("const jfloat ", stream);
5e74a4eb
TT
855 print_field_name (stream, jcf, name_index, 0);
856 jni_print_float (stream, fnum);
e04a16fb
AG
857 }
858 break;
859 case CONSTANT_Double:
860 {
861 jdouble dnum = JPOOL_DOUBLE (jcf, current_field_value);
5e74a4eb 862 if (! flag_jni)
22f8a068 863 fputs ("const jdouble ", stream);
5e74a4eb
TT
864 print_field_name (stream, jcf, name_index, 0);
865 jni_print_double (stream, dnum);
e04a16fb
AG
866 }
867 break;
868 default:
5877286e
TT
869 /* We can't print this as a constant, but we can still
870 print something sensible. */
871 done = 0;
872 break;
e04a16fb
AG
873 }
874
5877286e
TT
875 if (done)
876 return;
e04a16fb
AG
877 }
878 }
879
5e74a4eb 880 /* assert (! flag_jni); */
5877286e 881 override = get_field_name (jcf, name_index, flags);
5e74a4eb
TT
882 print_c_decl (stream, jcf, name_index, sig_index, 0, override, flags);
883 fputs (";\n", stream);
e4de5a10
PB
884
885 if (override)
886 free (override);
e04a16fb
AG
887}
888
1bbee75b 889
e04a16fb 890static void
6ff2fe39
KG
891print_method_info (FILE *stream, JCF* jcf, int name_index, int sig_index,
892 JCF_u2 flags)
e04a16fb 893{
be245ac0 894 const unsigned char *str;
e04a16fb 895 int length, is_init = 0;
83c1f628 896 char *override = NULL;
e04a16fb 897
8c2dfb32 898 method_declared = 0;
cb975f38 899 method_access = flags;
de380723 900 if (stream && JPOOL_TAG (jcf, name_index) != CONSTANT_Utf8)
e04a16fb
AG
901 fprintf (stream, "<not a UTF8 constant>");
902 str = JPOOL_UTF_DATA (jcf, name_index);
903 length = JPOOL_UTF_LENGTH (jcf, name_index);
f0f3a777 904
f0f3a777 905 if (str[0] == '<')
e04a16fb 906 {
f0f3a777
APB
907 /* Ignore the internally generated method <clinit>. However,
908 treat <init> as a constructor. */
e04a16fb
AG
909 if (! utf8_cmp (str, length, "<init>"))
910 is_init = 1;
bdb59aec
TT
911 else if (! METHOD_IS_FINAL (jcf->access_flags, flags)
912 && ! (flags & ACC_STATIC))
913 {
914 /* FIXME: i18n bug here. Order of prints should not be
915 fixed. */
597cdf4f 916 fprintf (stderr, _("ignored method '"));
bdb59aec 917 jcf_print_utf8 (stderr, str, length);
0237b2dc 918 fprintf (stderr, _("' marked virtual\n"));
bdb59aec
TT
919 found_error = 1;
920 return;
921 }
922 else
e04a16fb
AG
923 return;
924 }
1bbee75b
BM
925
926 /* During the first method pass, build a list of method names. This will
927 be used to determine if field names conflict with method names. */
928 if (! stream)
e4de5a10
PB
929 {
930 struct method_name *nn;
931
5ed6ace5
MD
932 nn = XNEW (struct method_name);
933 nn->name = XNEWVEC (unsigned char, length);
e4de5a10
PB
934 memcpy (nn->name, str, length);
935 nn->length = length;
936 nn->next = method_name_list;
de380723 937 nn->sig_length = JPOOL_UTF_LENGTH (jcf, sig_index);
5ed6ace5 938 nn->signature = XNEWVEC (unsigned char, nn->sig_length);
3fb577a5 939 nn->is_native = METHOD_IS_NATIVE (flags);
de380723
TT
940 memcpy (nn->signature, JPOOL_UTF_DATA (jcf, sig_index),
941 nn->sig_length);
e4de5a10 942 method_name_list = nn;
1bbee75b
BM
943
944 /* The rest of this function doesn't matter. */
945 return;
e4de5a10 946 }
e04a16fb 947
c45c5e09
TT
948 /* We don't worry about overrides in JNI mode. */
949 if (! flag_jni)
e4de5a10 950 {
c45c5e09
TT
951 /* We can't generate a method whose name is a C++ reserved word.
952 We can't just ignore the function, because that will cause
953 incorrect code to be generated if the function is virtual
954 (not only for calls to this function for for other functions
955 after it in the vtbl). So we give it a dummy name instead. */
956 override = cxx_keyword_subst (str, length);
e4de5a10 957 }
e04a16fb 958
de380723 959 if (! stubs && ! flag_jni)
e04a16fb 960 {
6c9c5c1f 961 method_printed = 1;
8c2dfb32 962
6c9c5c1f
AG
963 generate_access (stream, flags);
964
965 fputs (" ", out);
966 if ((flags & ACC_STATIC))
967 fputs ("static ", out);
36739040 968 else if (! METHOD_IS_PRIVATE (jcf->access_flags, flags))
6c9c5c1f
AG
969 {
970 /* Don't print `virtual' if we have a constructor. */
971 if (! is_init)
972 fputs ("virtual ", out);
973 }
de380723 974 print_c_decl (out, jcf, name_index, sig_index, is_init, override, flags);
6c9c5c1f
AG
975
976 if ((flags & ACC_ABSTRACT))
977 fputs (" = 0", out);
978 else
979 method_declared = 1;
980 }
8c2dfb32 981 else
6c9c5c1f 982 {
de380723 983 if (METHOD_IS_NATIVE (flags))
6c9c5c1f
AG
984 {
985 method_printed = 1;
de380723
TT
986 print_stub_or_jni (out, jcf, name_index, sig_index,
987 is_init, override, flags);
6c9c5c1f
AG
988 }
989 }
83c1f628
TT
990
991 if (override)
992 free (override);
92c068d1 993}
e04a16fb 994
150f086d
TT
995/* A helper for the decompiler which prints a `return' statement where
996 the type is a reference type. If METHODTYPE and OBJECTTYPE are not
997 identical, we emit a cast. We do this because the C++ compiler
998 doesn't know that a reference can be cast to the type of an
999 interface it implements. METHODTYPE is the index of the method's
1000 signature. NAMEINDEX is the index of the field name; -1 for
1001 `this'. OBJECTTYPE is the index of the object's type. */
1002static void
0a2f0c54
KG
1003decompile_return_statement (FILE *out, JCF *jcf, int methodtype,
1004 int nameindex, int objecttype)
150f086d
TT
1005{
1006 int cast = 0;
1007 int obj_name_len, method_name_len;
1008 const unsigned char *obj_data, *method_data;
1009
1010 obj_name_len = JPOOL_UTF_LENGTH (jcf, objecttype);
1011 obj_data = JPOOL_UTF_DATA (jcf, objecttype);
1012
1013 method_name_len = JPOOL_UTF_LENGTH (jcf, methodtype);
1014 method_data = JPOOL_UTF_DATA (jcf, methodtype);
1015
1016 /* Skip forward to return type part of method. */
1017 while (*method_data != ')')
1018 {
1019 ++method_data;
1020 --method_name_len;
1021 }
1022 /* Skip past `)'. */
1023 ++method_data;
1024 --method_name_len;
1025
1026 /* If we see an `L', skip it and the trailing `;'. */
1027 if (method_data[0] == 'L' && method_data[method_name_len - 1] == ';')
1028 {
1029 ++method_data;
1030 method_name_len -= 2;
1031 }
1032 if (obj_data[0] == 'L' && obj_data[obj_name_len - 1] == ';')
1033 {
1034 ++obj_data;
1035 obj_name_len -= 2;
1036 }
1037
1038 /* FIXME: if METHODTYPE is a superclass of OBJECTTYPE then we don't
1039 need a cast. Right now there is no way to determine if this is
1040 the case. */
1041 if (method_name_len != obj_name_len)
1042 cast = 1;
1043 else
1044 {
1045 int i;
1046 for (i = 0; i < method_name_len; ++i)
1047 {
1048 if (method_data[i] != obj_data[i])
1049 {
1050 cast = 1;
1051 break;
1052 }
1053 }
1054 }
1055
1056 fputs (" { return ", out);
1057
1058 if (cast)
1059 {
1060 int array_depth = 0;
1061 const unsigned char *limit;
1062
1063 fputs ("reinterpret_cast<", out);
1064
1065 while (*method_data == '[')
1066 {
1067 ++method_data;
1068 ++array_depth;
1069 --method_name_len;
1070 fputs ("JArray<", out);
1071 }
1072
1073 /* Leading space to avoid C++ digraphs. */
1074 fputs (" ::", out);
1075
1076 /* If we see an `L', skip it and the trailing `;'. Only do this
1077 if we've seen an array specification. If we don't have an
1078 array then the `L' was stripped earlier. */
1079 if (array_depth && method_data[0] == 'L'
1080 && method_data[method_name_len - 1] == ';')
1081 {
1082 ++method_data;
1083 method_name_len -= 2;
1084 }
1085
1086 limit = method_data + method_name_len;
1087 while (method_data < limit)
1088 {
1089 int ch = UTF8_GET (method_data, limit);
1090 if (ch == '/')
1091 fputs ("::", out);
1092 else
1093 jcf_print_char (out, ch);
1094 }
1095 fputs (" *", out);
1096
1097 /* Close each array. */
1098 while (array_depth > 0)
1099 {
1100 fputs ("> *", out);
1101 --array_depth;
1102 }
1103
1104 /* Close the cast. */
1105 fputs ("> (", out);
1106 }
1107
1108 if (nameindex == -1)
1109 fputs ("this", out);
1110 else
1111 print_field_name (out, jcf, nameindex, 0);
1112
1113 if (cast)
1114 fputs (")", out);
1115
1116 fputs ("; }", out);
1117}
1118
1119
92c068d1
TT
1120/* Try to decompile a method body. Right now we just try to handle a
1121 simple case that we can do. Expand as desired. */
1122static void
0a2f0c54 1123decompile_method (FILE *out, JCF *jcf, int code_len)
92c068d1 1124{
be245ac0 1125 const unsigned char *codes = jcf->read_ptr;
92c068d1
TT
1126 int index;
1127 uint16 name_and_type, name;
1128
cb975f38
TT
1129 /* If the method is synchronized, don't touch it. */
1130 if ((method_access & ACC_SYNCHRONIZED))
1131 return;
1132
92c068d1
TT
1133 if (code_len == 5
1134 && codes[0] == OPCODE_aload_0
1135 && codes[1] == OPCODE_getfield
cb975f38
TT
1136 && (codes[4] == OPCODE_areturn
1137 || codes[4] == OPCODE_dreturn
1138 || codes[4] == OPCODE_freturn
1139 || codes[4] == OPCODE_ireturn
1140 || codes[4] == OPCODE_lreturn))
92c068d1 1141 {
cb975f38 1142 /* Found code like `return FIELD'. */
92c068d1
TT
1143 index = (codes[2] << 8) | codes[3];
1144 /* FIXME: ensure that tag is CONSTANT_Fieldref. */
92c068d1
TT
1145 name_and_type = JPOOL_USHORT2 (jcf, index);
1146 /* FIXME: ensure that tag is CONSTANT_NameAndType. */
1147 name = JPOOL_USHORT1 (jcf, name_and_type);
150f086d
TT
1148 if (codes[4] == OPCODE_areturn)
1149 decompile_return_statement (out, jcf, method_signature,
1150 name, JPOOL_USHORT2 (jcf, name_and_type));
1151 else
1152 {
1153 fputs (" { return ", out);
1154 /* FIXME: flags. */
1155 print_field_name (out, jcf, name, 0);
1156 fputs ("; }", out);
1157 }
92c068d1
TT
1158 decompiled = 1;
1159 }
cb975f38
TT
1160 else if (code_len == 2
1161 && codes[0] == OPCODE_aload_0
5fcab235
TT
1162 && codes[1] == OPCODE_areturn
1163 /* We're going to generate `return this'. This only makes
1164 sense for non-static methods. */
1165 && ! (method_access & ACC_STATIC))
cb975f38 1166 {
150f086d
TT
1167 decompile_return_statement (out, jcf, method_signature, -1,
1168 JPOOL_USHORT1 (jcf, jcf->this_class));
cb975f38
TT
1169 decompiled = 1;
1170 }
1171 else if (code_len == 1 && codes[0] == OPCODE_return)
1172 {
1173 /* Found plain `return'. */
1174 fputs (" { }", out);
1175 decompiled = 1;
1176 }
8c2dfb32
TT
1177 else if (code_len == 2
1178 && codes[0] == OPCODE_aconst_null
1179 && codes[1] == OPCODE_areturn)
1180 {
1181 /* Found `return null'. We don't want to depend on NULL being
1182 defined. */
1183 fputs (" { return 0; }", out);
1184 decompiled = 1;
1185 }
e04a16fb
AG
1186}
1187
6b9b5de2
TT
1188/* Like strcmp, but invert the return result for the hash table. This
1189 should probably be in hashtab.c to complement the existing string
1190 hash function. */
1191static int
0a2f0c54 1192gcjh_streq (const void *p1, const void *p2)
6b9b5de2
TT
1193{
1194 return ! strcmp ((char *) p1, (char *) p2);
1195}
1196
64e68197
BM
1197/* Return 1 if the initial part of CLNAME names a subclass of throwable,
1198 or 0 if not. CLNAME may be extracted from a signature, and can be
1199 terminated with either `;' or NULL. */
6b9b5de2 1200static int
0a2f0c54 1201throwable_p (const unsigned char *clname)
6b9b5de2
TT
1202{
1203 int length;
1204 unsigned char *current;
1205 int i;
1206 int result = 0;
1207
1208 /* We keep two hash tables of class names. In one we list all the
1209 classes which are subclasses of Throwable. In the other we will
1210 all other classes. We keep two tables to make the code a bit
1211 simpler; we don't have to have a structure mapping class name to
1212 a `throwable?' bit. */
1213 static htab_t throw_hash;
1214 static htab_t non_throw_hash;
1215 static int init_done = 0;
1216
1217 if (! init_done)
1218 {
77d3109b
KG
1219 void **slot;
1220 unsigned char *str;
6b9b5de2
TT
1221
1222 /* Self-initializing. The cost of this really doesn't matter.
1223 We also don't care about freeing these, either. */
1224 throw_hash = htab_create (10, htab_hash_string, gcjh_streq,
1225 (htab_del) free);
1226 non_throw_hash = htab_create (10, htab_hash_string, gcjh_streq,
1227 (htab_del) free);
1228
1229 /* Make sure the root classes show up in the tables. */
0e7d217a 1230 str = (unsigned char *) xstrdup ("java.lang.Throwable");
6b9b5de2 1231 slot = htab_find_slot (throw_hash, str, INSERT);
77d3109b 1232 *slot = str;
6b9b5de2 1233
0e7d217a 1234 str = (unsigned char *) xstrdup ("java.lang.Object");
6b9b5de2 1235 slot = htab_find_slot (non_throw_hash, str, INSERT);
77d3109b 1236 *slot = str;
6b9b5de2
TT
1237
1238 init_done = 1;
1239 }
1240
64e68197 1241 for (length = 0; clname[length] != ';' && clname[length] != '\0'; ++length)
6b9b5de2 1242 ;
5ed6ace5 1243 current = XNEWVEC (unsigned char, length + 1);
64e68197
BM
1244 for (i = 0; i < length; ++i)
1245 current[i] = clname[i] == '/' ? '.' : clname[i];
1246 current[length] = '\0';
6b9b5de2
TT
1247
1248 /* We don't compute the hash slot here because the table might be
1249 modified by the recursion. In that case the slot could be
1250 invalidated. */
1251 if (htab_find (throw_hash, current))
1252 result = 1;
1253 else if (htab_find (non_throw_hash, current))
1254 result = 0;
1255 else
1256 {
1257 JCF jcf;
77d3109b 1258 void **slot;
64e68197
BM
1259 unsigned char *super, *tmp;
1260 int super_length = -1;
0e7d217a 1261 const char *classfile_name = find_class ((char *) current, strlen ((const char *) current),
6b9b5de2
TT
1262 &jcf, 0);
1263
1264 if (! classfile_name)
1265 {
0237b2dc 1266 error ("couldn't find class %s", current);
6b9b5de2
TT
1267 return 0;
1268 }
1269 if (jcf_parse_preamble (&jcf) != 0
1270 || jcf_parse_constant_pool (&jcf) != 0
1271 || verify_constant_pool (&jcf) > 0)
1272 {
0237b2dc 1273 error ("parse error while reading %s", classfile_name);
6b9b5de2
TT
1274 return 0;
1275 }
1276 jcf_parse_class (&jcf);
1277
64e68197 1278 tmp = (unsigned char *) super_class_name (&jcf, &super_length);
5ed6ace5 1279 super = XNEWVEC (unsigned char, super_length + 1);
64e68197
BM
1280 memcpy (super, tmp, super_length);
1281 super[super_length] = '\0';
1282
1283 result = throwable_p (super);
6b9b5de2
TT
1284 slot = htab_find_slot (result ? throw_hash : non_throw_hash,
1285 current, INSERT);
1286 *slot = current;
1287 current = NULL;
1288
1289 JCF_FINISH (&jcf);
1290 }
1291
6b9b5de2
TT
1292 return result;
1293}
1294
e4de5a10
PB
1295/* Print one piece of a signature. Returns pointer to next parseable
1296 character on success, NULL on error. */
be245ac0 1297static const unsigned char *
0a2f0c54
KG
1298decode_signature_piece (FILE *stream, const unsigned char *signature,
1299 const unsigned char *limit, int *need_space)
e4de5a10 1300{
d4476be2 1301 const char *ctype;
3a5395a3 1302 int array_depth = 0;
e4de5a10
PB
1303
1304 switch (signature[0])
1305 {
1306 case '[':
3a5395a3 1307 /* More spaghetti. */
de380723 1308
3a5395a3 1309 array_loop:
e4de5a10 1310 for (signature++; (signature < limit
0df6c2c7 1311 && ISDIGIT (*signature)); signature++)
e4de5a10
PB
1312 ;
1313 switch (*signature)
1314 {
de380723
TT
1315 case 'B':
1316 ctype = "jbyteArray";
1317 break;
1318 case 'C':
1319 ctype = "jcharArray";
1320 break;
1321 case 'D':
1322 ctype = "jdoubleArray";
1323 break;
1324 case 'F':
1325 ctype = "jfloatArray";
1326 break;
1327 case 'I':
1328 ctype = "jintArray";
1329 break;
1330 case 'S':
1331 ctype = "jshortArray";
1332 break;
1333 case 'J':
1334 ctype = "jlongArray";
1335 break;
1336 case 'Z':
1337 ctype = "jbooleanArray";
1338 break;
3a5395a3
TT
1339 case '[':
1340 /* We have a nested array. */
1341 ++array_depth;
de380723
TT
1342 if (! flag_jni)
1343 fputs ("JArray<", stream);
3a5395a3
TT
1344 goto array_loop;
1345
e4de5a10 1346 case 'L':
3a5395a3
TT
1347 /* We have to generate a reference to JArray here, so that
1348 our output matches what the compiler does. */
e4de5a10 1349 ++signature;
6f19291a 1350 /* Space between `<' and `:' to avoid C++ digraphs. */
de380723
TT
1351 if (! flag_jni)
1352 fputs ("JArray< ::", stream);
e4de5a10
PB
1353 while (signature < limit && *signature != ';')
1354 {
1355 int ch = UTF8_GET (signature, limit);
de380723
TT
1356 if (! flag_jni)
1357 {
1358 if (ch == '/')
1359 fputs ("::", stream);
1360 else
1361 jcf_print_char (stream, ch);
1362 }
e4de5a10 1363 }
de380723
TT
1364 if (! flag_jni)
1365 fputs (" *> *", stream);
e4de5a10 1366 *need_space = 0;
de380723 1367 ctype = NULL;
e4de5a10
PB
1368 break;
1369 default:
1370 /* Unparseable signature. */
1371 return NULL;
1372 }
de380723
TT
1373
1374 /* If the previous iterations left us with something to print,
1375 print it. For JNI, we always print `jobjectArray' in the
1376 nested cases. */
0d3911c9 1377 if (flag_jni && (ctype == NULL || array_depth > 0))
de380723
TT
1378 {
1379 ctype = "jobjectArray";
1380 *need_space = 1;
1381 }
1382 /* The `printit' case will advance SIGNATURE for us. If we
1383 don't go there, we must advance past the `;' ourselves. */
1384 if (ctype != NULL)
1385 goto printit;
1386 ++signature;
e4de5a10
PB
1387 break;
1388
1389 case '(':
1390 case ')':
1391 /* This shouldn't happen. */
1392 return NULL;
1393
1394 case 'B': ctype = "jbyte"; goto printit;
1395 case 'C': ctype = "jchar"; goto printit;
1396 case 'D': ctype = "jdouble"; goto printit;
1397 case 'F': ctype = "jfloat"; goto printit;
1398 case 'I': ctype = "jint"; goto printit;
1399 case 'J': ctype = "jlong"; goto printit;
1400 case 'S': ctype = "jshort"; goto printit;
1401 case 'Z': ctype = "jboolean"; goto printit;
1402 case 'V': ctype = "void"; goto printit;
1403 case 'L':
de380723
TT
1404 if (flag_jni)
1405 {
6b9b5de2 1406 /* We know about certain types and special-case their names. */
0e7d217a 1407 if (! strncmp ((const char *) signature, "Ljava/lang/String;",
de380723
TT
1408 sizeof ("Ljava/lang/String;") -1))
1409 ctype = "jstring";
0e7d217a 1410 else if (! strncmp ((const char *) signature, "Ljava/lang/Class;",
de380723
TT
1411 sizeof ("Ljava/lang/Class;") - 1))
1412 ctype = "jclass";
64e68197
BM
1413 /* Skip leading 'L' for throwable_p call. */
1414 else if (throwable_p (signature + 1))
de380723 1415 ctype = "jthrowable";
de380723
TT
1416 else
1417 ctype = "jobject";
1418
1419 while (*signature && *signature != ';')
1420 ++signature;
1421
1422 goto printit;
1423 }
12207a87
TT
1424 /* Print a leading "::" so we look in the right namespace. */
1425 fputs ("::", stream);
e4de5a10
PB
1426 ++signature;
1427 while (*signature && *signature != ';')
1428 {
1429 int ch = UTF8_GET (signature, limit);
dd5d6281 1430 if (ch == '/')
e4de5a10
PB
1431 fputs ("::", stream);
1432 else
1433 jcf_print_char (stream, ch);
1434 }
1435 fputs (" *", stream);
1436 if (*signature == ';')
1437 signature++;
1438 *need_space = 0;
1439 break;
1440 default:
1441 *need_space = 1;
78de74be 1442 jni_print_char (stream, *signature++);
e4de5a10
PB
1443 break;
1444 printit:
1445 signature++;
1446 *need_space = 1;
1447 fputs (ctype, stream);
1448 break;
1449 }
1450
de380723
TT
1451 if (! flag_jni)
1452 {
1453 while (array_depth-- > 0)
1454 fputs ("> *", stream);
1455 }
3a5395a3 1456
e4de5a10
PB
1457 return signature;
1458}
1459
e04a16fb 1460static void
6ff2fe39
KG
1461print_c_decl (FILE* stream, JCF* jcf, int name_index, int signature_index,
1462 int is_init, const char *name_override, int flags)
e04a16fb
AG
1463{
1464 if (JPOOL_TAG (jcf, signature_index) != CONSTANT_Utf8)
e4de5a10
PB
1465 {
1466 fprintf (stream, "<not a UTF8 constant>");
1467 found_error = 1;
1468 }
e04a16fb
AG
1469 else
1470 {
1471 int length = JPOOL_UTF_LENGTH (jcf, signature_index);
be245ac0 1472 const unsigned char *str0 = JPOOL_UTF_DATA (jcf, signature_index);
3a976c72 1473 const unsigned char *str = str0;
be245ac0 1474 const unsigned char *limit = str + length;
e04a16fb
AG
1475 int need_space = 0;
1476 int is_method = str[0] == '(';
be245ac0 1477 const unsigned char *next;
e04a16fb 1478
e4de5a10
PB
1479 /* If printing a method, skip to the return signature and print
1480 that first. However, there is no return value if this is a
1481 constructor. */
1482 if (is_method && ! is_init)
e04a16fb 1483 {
e4de5a10 1484 while (str < limit)
e04a16fb 1485 {
e4de5a10
PB
1486 int ch = *str++;
1487 if (ch == ')')
1488 break;
e04a16fb
AG
1489 }
1490 }
1491
e4de5a10
PB
1492 /* If printing a field or an ordinary method, then print the
1493 "return value" now. */
1494 if (! is_method || ! is_init)
e04a16fb 1495 {
e4de5a10
PB
1496 next = decode_signature_piece (stream, str, limit, &need_space);
1497 if (! next)
e04a16fb 1498 {
597cdf4f 1499 error ("unparseable signature: '%s'", str0);
e04a16fb 1500 return;
e04a16fb 1501 }
e04a16fb 1502 }
e4de5a10 1503
68566610 1504 /* Force the alignment of the first data member. This is
c048d56d 1505 because the "new" C++ ABI changed the alignment of non-POD
68566610
AH
1506 classes. gcj, however, still uses the "old" alignment. */
1507 if (is_first_data_member && ! (flags & ACC_STATIC) && ! is_method)
e6311b9e
TT
1508 {
1509 is_first_data_member = 0;
1510 print_cxx_classname (out, " __attribute__((aligned(__alignof__( ",
1511 jcf, jcf->super_class, 1);
1512 fputs (" )))) ", stream);
1513 }
68566610 1514
e4de5a10
PB
1515 /* Now print the name of the thing. */
1516 if (need_space)
1517 fputs (" ", stream);
6c9c5c1f 1518 print_full_cxx_name (stream, jcf, name_index,
de380723
TT
1519 signature_index, is_init, name_override,
1520 flags);
6c9c5c1f
AG
1521 }
1522}
1523
5f9ee695 1524/* Print the unqualified method name followed by the signature. */
6c9c5c1f 1525static void
6ff2fe39
KG
1526print_full_cxx_name (FILE* stream, JCF* jcf, int name_index,
1527 int signature_index, int is_init,
1528 const char *name_override, int flags)
6c9c5c1f
AG
1529{
1530 int length = JPOOL_UTF_LENGTH (jcf, signature_index);
be245ac0 1531 const unsigned char *str0 = JPOOL_UTF_DATA (jcf, signature_index);
3a976c72 1532 const unsigned char *str = str0;
be245ac0 1533 const unsigned char *limit = str + length;
6c9c5c1f
AG
1534 int need_space = 0;
1535 int is_method = str[0] == '(';
be245ac0 1536 const unsigned char *next;
6c9c5c1f
AG
1537
1538 if (name_override)
1539 fputs (name_override, stream);
1540 else if (name_index)
1541 {
1542 /* Declare constructors specially. */
1543 if (is_init)
1544 print_base_classname (stream, jcf, jcf->this_class);
1545 else
1546 print_name (stream, jcf, name_index);
1547 }
de380723
TT
1548
1549 if (flag_jni)
1550 {
1551 unsigned char *signature = JPOOL_UTF_DATA (jcf, signature_index);
1552 int sig_len = JPOOL_UTF_LENGTH (jcf, signature_index);
1553 if (overloaded_jni_method_exists_p (JPOOL_UTF_DATA (jcf, name_index),
1554 JPOOL_UTF_LENGTH (jcf, name_index),
0e7d217a 1555 (const char *) signature, sig_len))
de380723
TT
1556 {
1557 /* If this method is overloaded by another native method,
1558 then include the argument information in the mangled
1559 name. */
1560 unsigned char *limit = signature + sig_len;
1561 fputs ("__", stream);
1562 while (signature < limit)
1563 {
1564 int ch = UTF8_GET (signature, limit);
78de74be
TT
1565 jni_print_char (stream, ch);
1566 if (ch == ')')
de380723
TT
1567 {
1568 /* Done. */
1569 break;
1570 }
de380723
TT
1571 }
1572 }
1573 }
1574
6c9c5c1f
AG
1575 if (is_method)
1576 {
1577 /* Have a method or a constructor. Print signature pieces
1578 until done. */
1579 fputs (" (", stream);
de380723 1580
6c9c5c1f 1581 str = str0 + 1;
de380723
TT
1582
1583 /* In JNI mode, add extra arguments. */
1584 if (flag_jni)
1585 {
1586 /* FIXME: it would be nice to know if we are printing a decl
1587 or a definition, and only print `env' for the latter. */
1588 fputs ("JNIEnv *env", stream);
1589
1590 fputs ((flags & ACC_STATIC) ? ", jclass" : ", jobject", stream);
1591
1592 if (*str != ')')
1593 fputs (", ", stream);
1594 }
1595
6c9c5c1f 1596 while (str < limit && *str != ')')
e04a16fb 1597 {
6c9c5c1f
AG
1598 next = decode_signature_piece (stream, str, limit, &need_space);
1599 if (! next)
1600 {
597cdf4f 1601 error ("unparseable signature: '%s'", str0);
6c9c5c1f
AG
1602 return;
1603 }
1604
1605 if (next < limit && *next != ')')
1606 fputs (", ", stream);
1607 str = next;
e04a16fb 1608 }
6c9c5c1f
AG
1609
1610 fputs (")", stream);
1611 }
1612}
c89c53eb 1613
de380723 1614/* This is a helper for print_stub_or_jni. */
6c9c5c1f 1615static void
6ff2fe39
KG
1616print_name_for_stub_or_jni (FILE *stream, JCF *jcf, int name_index,
1617 int signature_index, int is_init,
1618 const char *name_override, int flags)
de380723 1619{
a7384840 1620 const char *const prefix = flag_jni ? "Java_" : "";
239b7dea 1621 print_cxx_classname (stream, prefix, jcf, jcf->this_class, 1);
de380723
TT
1622 fputs (flag_jni ? "_" : "::", stream);
1623 print_full_cxx_name (stream, jcf, name_index,
1624 signature_index, is_init, name_override,
1625 flags);
1626}
1627
1628static void
6ff2fe39
KG
1629print_stub_or_jni (FILE* stream, JCF* jcf, int name_index,
1630 int signature_index, int is_init,
1631 const char *name_override, int flags)
6c9c5c1f
AG
1632{
1633 if (JPOOL_TAG (jcf, signature_index) != CONSTANT_Utf8)
1634 {
1635 fprintf (stream, "<not a UTF8 constant>");
1636 found_error = 1;
1637 }
1638 else
1639 {
1640 int length = JPOOL_UTF_LENGTH (jcf, signature_index);
be245ac0 1641 const unsigned char *str0 = JPOOL_UTF_DATA (jcf, signature_index);
3a976c72 1642 const unsigned char *str = str0;
be245ac0 1643 const unsigned char *limit = str + length;
6c9c5c1f
AG
1644 int need_space = 0;
1645 int is_method = str[0] == '(';
be245ac0 1646 const unsigned char *next;
e4de5a10 1647
de380723
TT
1648 /* Don't print fields in the JNI case. */
1649 if (! is_method && flag_jni)
1650 return;
1651
1652 if (flag_jni && ! stubs)
f1865cde 1653 fputs ("JNIEXPORT ", stream);
de380723 1654
6c9c5c1f
AG
1655 /* If printing a method, skip to the return signature and print
1656 that first. However, there is no return value if this is a
1657 constructor. */
1658 if (is_method && ! is_init)
e04a16fb 1659 {
6c9c5c1f 1660 while (str < limit)
e4de5a10 1661 {
6c9c5c1f
AG
1662 int ch = *str++;
1663 if (ch == ')')
1664 break;
e4de5a10 1665 }
6c9c5c1f 1666 }
e4de5a10 1667
6c9c5c1f 1668 /* If printing a field or an ordinary method, then print the
de380723
TT
1669 "return value" now. Note that a constructor can't be native,
1670 so we don't bother checking this in the JNI case. */
6c9c5c1f
AG
1671 if (! is_method || ! is_init)
1672 {
1673 next = decode_signature_piece (stream, str, limit, &need_space);
1674 if (! next)
1675 {
597cdf4f 1676 error ("unparseable signature: '%s'", str0);
6c9c5c1f
AG
1677 return;
1678 }
e04a16fb 1679 }
6c9c5c1f 1680
de380723
TT
1681 /* When printing a JNI header we need to respect the space. In
1682 other cases we're just going to insert a newline anyway. */
a7384840 1683 fputs (need_space && ! stubs ? " " : "\n", stream);
5bd717f1
TT
1684
1685 if (flag_jni && ! stubs)
1686 fputs ("JNICALL ", stream);
a7384840 1687
6c9c5c1f 1688 /* Now print the name of the thing. */
de380723
TT
1689 print_name_for_stub_or_jni (stream, jcf, name_index,
1690 signature_index, is_init, name_override,
1691 flags);
1692
1693 /* Print the body. */
1694 if (stubs)
1695 {
1696 if (flag_jni)
45c00e22 1697 fputs ("\n{\n (*env)->FatalError (env, \"", stream);
de380723 1698 else
0df29596 1699 fputs ("\n{\n throw new ::java::lang::UnsupportedOperationException (JvNewStringLatin1 (\"", stream);
de380723
TT
1700 print_name_for_stub_or_jni (stream, jcf, name_index,
1701 signature_index, is_init,
1702 name_override,
1703 flags);
0df29596
TT
1704 fprintf (stream, " not implemented\")%s;\n}\n\n",
1705 flag_jni ? "" : ")");
de380723 1706 }
e04a16fb
AG
1707 }
1708}
1709
be245ac0 1710static void
6ff2fe39 1711print_mangled_classname (FILE *stream, JCF *jcf, const char *prefix, int index)
e04a16fb
AG
1712{
1713 int name_index = JPOOL_USHORT1 (jcf, index);
1714 fputs (prefix, stream);
1715 jcf_print_utf8_replace (out,
1716 JPOOL_UTF_DATA (jcf, name_index),
1717 JPOOL_UTF_LENGTH (jcf, name_index),
1718 '/', '_');
1719}
1720
1721/* Print PREFIX, then a class name in C++ format. If the name refers
1722 to an array, ignore it and don't print PREFIX. Returns 1 if
1723 something was printed, 0 otherwise. */
1724static int
0a2f0c54
KG
1725print_cxx_classname (FILE *stream, const char *prefix,
1726 JCF *jcf, int index, int add_scope)
e04a16fb
AG
1727{
1728 int name_index = JPOOL_USHORT1 (jcf, index);
fc45c7ef 1729 int len, c;
be245ac0 1730 const unsigned char *s, *p, *limit;
e04a16fb
AG
1731
1732 s = JPOOL_UTF_DATA (jcf, name_index);
1733 len = JPOOL_UTF_LENGTH (jcf, name_index);
1734 limit = s + len;
1735
1736 /* Explicitly omit arrays here. */
1737 p = s;
1738 c = UTF8_GET (p, limit);
1739 if (c == '[')
1740 return 0;
1741
1742 fputs (prefix, stream);
12207a87
TT
1743
1744 /* Print a leading "::" so we look in the right namespace. */
239b7dea 1745 if (! flag_jni && ! stubs && add_scope)
de380723 1746 fputs ("::", stream);
12207a87 1747
e04a16fb
AG
1748 while (s < limit)
1749 {
1750 c = UTF8_GET (s, limit);
1751 if (c == '/')
de380723 1752 fputs (flag_jni ? "_" : "::", stream);
e04a16fb 1753 else
78de74be 1754 jni_print_char (stream, c);
e04a16fb
AG
1755 }
1756
1757 return 1;
1758}
1759
1760int written_class_count = 0;
1761
1762/* Return name of superclass. If LEN is not NULL, fill it with length
1763 of name. */
be245ac0 1764static const unsigned char *
0a2f0c54 1765super_class_name (JCF *derived_jcf, int *len)
e04a16fb
AG
1766{
1767 int supername_index = JPOOL_USHORT1 (derived_jcf, derived_jcf->super_class);
1768 int supername_length = JPOOL_UTF_LENGTH (derived_jcf, supername_index);
be245ac0
KG
1769 const unsigned char *supername =
1770 JPOOL_UTF_DATA (derived_jcf, supername_index);
e04a16fb
AG
1771
1772 if (len)
1773 *len = supername_length;
1774
1775 return supername;
1776}
1777
73cb3b5a
TT
1778static void
1779handle_inner_classes (int count)
1780{
1781 int i;
1782
1783 if (out && ! flag_jni && ! stubs && count > 0)
1784 fprintf (out, "\n");
1785
1786 for (i = 0; i < count; ++i)
1787 {
1788 JCF_u2 inner_info_index = JCF_readu2 (current_jcf);
1789
1790 /* There are a few more values here, but we don't care about
1791 them. The (void) cast is apparently the only way to avoid a
1792 warning here. */
1793 (void) JCF_readu2 (current_jcf);
1794 (void) JCF_readu2 (current_jcf);
1795 (void) JCF_readu2 (current_jcf);
1796
1797 if (out && ! flag_jni && ! stubs)
1798 {
1799 print_mangled_classname (out, current_jcf, " friend class ",
1800 inner_info_index);
1801 fprintf (out, ";\n");
1802 }
1803 }
1804}
1805
bdb59aec
TT
1806\f
1807
686fb236
TT
1808/* We keep track of all the `#include's we generate, so we can avoid
1809 duplicates. */
1810struct include
1811{
1812 char *name;
1813 struct include *next;
1814};
1815
1816/* List of all includes. */
1817static struct include *all_includes = NULL;
1818
1819/* Generate a #include. */
1820static void
0a2f0c54 1821print_include (FILE *out, const unsigned char *utf8, int len)
686fb236
TT
1822{
1823 struct include *incl;
1824
1825 if (! out)
1826 return;
1827
1828 if (len == -1)
0e7d217a 1829 len = strlen ((const char *) utf8);
686fb236
TT
1830
1831 for (incl = all_includes; incl; incl = incl->next)
1832 {
5877286e 1833 /* We check the length because we might have a proper prefix. */
1b01250d 1834 if (len == (int) strlen (incl->name)
0e7d217a 1835 && ! strncmp (incl->name, (const char *) utf8, len))
686fb236
TT
1836 return;
1837 }
1838
5ed6ace5
MD
1839 incl = XNEW (struct include);
1840 incl->name = XNEWVEC (char, len + 1);
0e7d217a 1841 strncpy (incl->name, (const char *) utf8, len);
686fb236
TT
1842 incl->name[len] = '\0';
1843 incl->next = all_includes;
1844 all_includes = incl;
1845
1846 fputs ("#include <", out);
de380723
TT
1847 jcf_print_utf8_replace (out, utf8, len,
1848 '/',
1849 flag_jni ? '_' : '/');
686fb236
TT
1850 fputs (".h>\n", out);
1851}
1852
1853\f
1854
bdb59aec
TT
1855/* This is used to represent part of a package or class name. */
1856struct namelet
1857{
1858 /* The text of this part of the name. */
1859 char *name;
1860 /* True if this represents a class. */
1861 int is_class;
1862 /* Linked list of all classes and packages inside this one. */
1863 struct namelet *subnamelets;
1864 /* Pointer to next sibling. */
1865 struct namelet *next;
1866};
1867
d2097937
KG
1868static void add_namelet (const unsigned char *, const unsigned char *,
1869 struct namelet *);
1870static void print_namelet (FILE *, struct namelet *, int);
be245ac0 1871
bdb59aec
TT
1872/* The special root namelet. */
1873static struct namelet root =
1874{
1875 NULL,
1876 0,
1877 NULL,
1878 NULL
1879};
1880
1881/* This extracts the next name segment from the full UTF-8 encoded
1882 package or class name and links it into the tree. It does this
1883 recursively. */
e04a16fb 1884static void
0a2f0c54
KG
1885add_namelet (const unsigned char *name, const unsigned char *name_limit,
1886 struct namelet *parent)
bdb59aec 1887{
be245ac0 1888 const unsigned char *p;
bdb59aec
TT
1889 struct namelet *n = NULL, *np;
1890
f3d50f42
TT
1891 /* We want to skip the standard namespaces that we assume the
1892 runtime already knows about. We only do this at the top level,
1893 though, hence the check for `root'. */
1894 if (parent == &root)
1895 {
1896#define JAVALANG "java/lang/"
1897#define JAVAIO "java/io/"
1898#define JAVAUTIL "java/util/"
7e21fe59 1899 if ((name_limit - name >= (int) sizeof (JAVALANG) - 1
0e7d217a 1900 && ! strncmp ((const char *) name, JAVALANG, sizeof (JAVALANG) - 1))
7e21fe59 1901 || (name_limit - name >= (int) sizeof (JAVAUTIL) - 1
0e7d217a 1902 && ! strncmp ((const char *) name, JAVAUTIL, sizeof (JAVAUTIL) - 1))
7e21fe59 1903 || (name_limit - name >= (int) sizeof (JAVAIO) - 1
0e7d217a 1904 && ! strncmp ((const char *) name, JAVAIO, sizeof (JAVAIO) - 1)))
f3d50f42
TT
1905 return;
1906 }
1907
3c1d1e7b 1908 for (p = name; p < name_limit && *p != '/'; ++p)
bdb59aec
TT
1909 ;
1910
1911 /* Search for this name beneath the PARENT node. */
1912 for (np = parent->subnamelets; np != NULL; np = np->next)
1913 {
5877286e 1914 /* We check the length because we might have a proper prefix. */
1b01250d 1915 if ((int) strlen (np->name) == p - name &&
0e7d217a 1916 ! strncmp ((const char *) name, np->name, p - name))
bdb59aec
TT
1917 {
1918 n = np;
1919 break;
1920 }
1921 }
1922
1923 if (n == NULL)
1924 {
5ed6ace5
MD
1925 n = XNEW (struct namelet);
1926 n->name = XNEWVEC (char, p - name + 1);
0e7d217a 1927 strncpy (n->name, (const char *) name, p - name);
bdb59aec 1928 n->name[p - name] = '\0';
3c1d1e7b 1929 n->is_class = (p == name_limit);
bdb59aec
TT
1930 n->subnamelets = NULL;
1931 n->next = parent->subnamelets;
1932 parent->subnamelets = n;
1933 }
1934
1935 /* We recurse if there is more text, and if the trailing piece does
1936 not represent an inner class. */
3c1d1e7b 1937 if (p < name_limit)
bdb59aec
TT
1938 add_namelet (p + 1, name_limit, n);
1939}
1940
1941/* Print a single namelet. Destroys namelets while printing. */
1942static void
0a2f0c54 1943print_namelet (FILE *out, struct namelet *name, int depth)
bdb59aec
TT
1944{
1945 int i, term = 0;
1946 struct namelet *c;
1947
1948 if (name->name)
1949 {
1950 for (i = 0; i < depth; ++i)
1951 fputc (' ', out);
1952 fprintf (out, "%s %s", name->is_class ? "class" : "namespace",
1953 name->name);
1954 if (name->is_class && name->subnamelets == NULL)
1955 fputs (";\n", out);
1956 else
1957 {
1958 term = 1;
1959 fputs ("\n", out);
1960 for (i = 0; i < depth; ++i)
1961 fputc (' ', out);
1962 fputs ("{\n", out);
1963 }
1964 }
1965
1966 c = name->subnamelets;
1967 while (c != NULL)
1968 {
1969 struct namelet *next = c->next;
1970 print_namelet (out, c, depth + 2);
1971 c = next;
1972 }
4440ffc4 1973 name->subnamelets = NULL;
bdb59aec
TT
1974
1975 if (name->name)
1976 {
1977 if (term)
1978 {
1979 for (i = 0; i < depth; ++i)
1980 fputc (' ', out);
512d594b
TT
1981 fputs ("}\n", out);
1982 /* Only print a `;' when printing a class. C++ is evil. */
1983 if (name->is_class)
1984 fputs (";", out);
bdb59aec
TT
1985 }
1986
1987 free (name->name);
1988 free (name);
1989 }
1990}
1991
1992/* This is called to add some classes to the list of classes for which
1993 we need decls. The signature argument can be a function
1994 signature. */
1995static void
0a2f0c54 1996add_class_decl (FILE *out, JCF *jcf, JCF_u2 signature)
e04a16fb 1997{
be245ac0 1998 const unsigned char *s = JPOOL_UTF_DATA (jcf, signature);
bdb59aec
TT
1999 int len = JPOOL_UTF_LENGTH (jcf, signature);
2000 int i;
e04a16fb 2001
bdb59aec 2002 for (i = 0; i < len; ++i)
e04a16fb 2003 {
3c1d1e7b 2004 int start;
686fb236
TT
2005
2006 /* If we see an array, then we include the array header. */
2007 if (s[i] == '[')
2008 {
0e7d217a 2009 print_include (out, (const unsigned char *) "gcj/array", -1);
686fb236
TT
2010 continue;
2011 }
2012
bdb59aec
TT
2013 /* We're looking for `L<stuff>;' -- everything else is
2014 ignorable. */
2015 if (s[i] != 'L')
2016 continue;
686fb236 2017
bdb59aec 2018 for (start = ++i; i < len && s[i] != ';'; ++i)
3c1d1e7b 2019 ;
bdb59aec 2020
3c1d1e7b 2021 add_namelet (&s[start], &s[i], &root);
e04a16fb 2022 }
bdb59aec
TT
2023}
2024
2025/* Print declarations for all classes required by this class. Any
2026 class or package in the `java' package is assumed to be handled
2027 statically in libjava; we don't generate declarations for these.
2028 This makes the generated headers a bit easier to read. */
2029static void
0a2f0c54 2030print_class_decls (FILE *out, JCF *jcf, int self)
bdb59aec
TT
2031{
2032 /* Make sure to always add the current class to the list of things
2033 that should be declared. */
2034 int name_index = JPOOL_USHORT1 (jcf, self);
2035 int len;
be245ac0 2036 const unsigned char *s;
bdb59aec
TT
2037
2038 s = JPOOL_UTF_DATA (jcf, name_index);
2039 len = JPOOL_UTF_LENGTH (jcf, name_index);
2040 add_namelet (s, s + len, &root);
e04a16fb 2041
bdb59aec
TT
2042 if (root.subnamelets)
2043 {
2044 fputs ("extern \"Java\"\n{\n", out);
2045 /* We use an initial offset of 0 because the root namelet
2046 doesn't cause anything to print. */
2047 print_namelet (out, &root, 0);
239b7dea 2048 fputs ("}\n\n", out);
bdb59aec 2049 }
e04a16fb
AG
2050}
2051
bdb59aec
TT
2052\f
2053
e04a16fb 2054static void
6ff2fe39 2055process_file (JCF *jcf, FILE *out)
e04a16fb
AG
2056{
2057 int code, i;
bdb59aec 2058 uint32 field_start, method_end, method_start;
e04a16fb 2059
4f65832d 2060 current_jcf = jcf;
e04a16fb 2061
3217b0f3 2062 last_access = -1;
e04a16fb
AG
2063
2064 if (jcf_parse_preamble (jcf) != 0)
2065 {
0237b2dc 2066 error ("Not a valid Java .class file.");
e04a16fb
AG
2067 return;
2068 }
2069
2070 /* Parse and possibly print constant pool */
2071 code = jcf_parse_constant_pool (jcf);
2072 if (code != 0)
2073 {
0237b2dc 2074 error ("error while parsing constant pool");
e04a16fb
AG
2075 return;
2076 }
2077 code = verify_constant_pool (jcf);
2078 if (code > 0)
2079 {
0237b2dc 2080 error ("error in constant pool entry #%d", code);
e04a16fb
AG
2081 return;
2082 }
2083
2084 jcf_parse_class (jcf);
2085
fc45c7ef 2086 if (written_class_count++ == 0 && out)
cd531a2e 2087 {
5ca1627b 2088 const char *cstart, *cstart2, *mode, *cend, *what, *jflag;
de380723
TT
2089 if (flag_jni)
2090 {
2091 cstart = "/*";
2092 cstart2 = " ";
2093 cend = " */";
2094 mode = "";
2095 what = "JNI";
2096 jflag = " -jni";
2097 }
2098 else
2099 {
2100 cstart = "//";
2101 cstart2 = "//";
2102 cend = "";
2103 mode = " -*- c++ -*-";
2104 what = "CNI";
2105 jflag = "";
2106 }
2107
cd531a2e 2108 if (! stubs)
de380723
TT
2109 fprintf (out, "%s DO NOT EDIT THIS FILE - it is machine generated%s%s\n\n",
2110 cstart, mode, cend);
cd531a2e
KG
2111 else
2112 {
d8be0aab 2113 fprintf (out, "%s This file was created by `" TOOLNAME " -stubs%s'.%s\n\
de380723
TT
2114%s\n\
2115%s This file is intended to give you a head start on implementing native\n\
2116%s methods using %s.\n\
d8be0aab 2117%s Be aware: running `" TOOLNAME " -stubs %s' once more for this class may\n\
de380723
TT
2118%s overwrite any edits you have made to this file.%s\n\n",
2119 cstart, jflag, mode,
2120 cstart2,
2121 cstart2,
2122 cstart2,
2123 what,
2124 cstart2,
2125 jflag,
2126 cstart2,
2127 cend);
cd531a2e
KG
2128 }
2129 }
e04a16fb 2130
fc45c7ef
TT
2131 if (out)
2132 {
6c9c5c1f
AG
2133 if (! stubs)
2134 {
2135 print_mangled_classname (out, jcf, "#ifndef __", jcf->this_class);
2136 fprintf (out, "__\n");
de380723 2137
6c9c5c1f
AG
2138 print_mangled_classname (out, jcf, "#define __", jcf->this_class);
2139 fprintf (out, "__\n\n");
de380723
TT
2140
2141 if (flag_jni)
6c9c5c1f 2142 {
de380723
TT
2143 fprintf (out, "#include <jni.h>\n\n");
2144 fprintf (out, "#ifdef __cplusplus\n");
2145 fprintf (out, "extern \"C\"\n");
2146 fprintf (out, "{\n");
2147 fprintf (out, "#endif\n");
2148 }
2149 else
2150 {
2151 /* We do this to ensure that inline methods won't be
2152 `outlined' by g++. This works as long as method and
2153 fields are not added by the user. */
2154 fprintf (out, "#pragma interface\n");
2155
2156 if (jcf->super_class)
2157 {
2158 int super_length;
2159 const unsigned char *supername =
2160 super_class_name (jcf, &super_length);
2161
2162 fputs ("\n", out);
2163 print_include (out, supername, super_length);
2164 }
6c9c5c1f
AG
2165 }
2166 }
2167 else
2168 {
2169 /* Strip off the ".class" portion of the name when printing
2170 the include file name. */
9c874875
TT
2171 char *name;
2172 int i, len = strlen (jcf->classname);
de380723
TT
2173 if (len > 6 && ! strcmp (&jcf->classname[len - 6], ".class"))
2174 len -= 6;
9c874875 2175 /* Turn the class name into a file name. */
5ed6ace5 2176 name = XNEWVEC (char, len + 1);
9c874875
TT
2177 for (i = 0; i < len; ++i)
2178 name[i] = jcf->classname[i] == '.' ? '/' : jcf->classname[i];
2179 name[i] = '\0';
0e7d217a 2180 print_include (out, (const unsigned char *) name, len);
9c874875
TT
2181 free (name);
2182
136c35df 2183 if (! flag_jni)
0df29596 2184 {
0e7d217a
MS
2185 print_include (out, (const unsigned char *) "gcj/cni", -1);
2186 print_include (out, (const unsigned char *) "java/lang/UnsupportedOperationException",
0df29596
TT
2187 -1);
2188 }
6c9c5c1f 2189 }
e04a16fb
AG
2190 }
2191
bdb59aec
TT
2192 /* We want to parse the methods first. But we need to find where
2193 they start. So first we skip the fields, then parse the methods.
2194 Then we parse the fields and skip the methods. This is ugly, but
2195 not too bad since we need two full passes to get class decl
2196 information anyway. */
2197 field_pass = 0;
2198 field_start = JCF_TELL (jcf);
2199 jcf_parse_fields (jcf);
2200
2201 method_start = JCF_TELL (jcf);
2202 method_pass = 0;
2203 jcf_parse_methods (jcf);
2204
fc45c7ef 2205 if (out)
de380723 2206 fputs ("\n", out);
6c9c5c1f 2207
de380723
TT
2208 if (out && ! flag_jni)
2209 {
6c9c5c1f
AG
2210 if (! stubs)
2211 print_class_decls (out, jcf, jcf->this_class);
e04a16fb 2212
fc45c7ef
TT
2213 for (i = 0; i < prepend_count; ++i)
2214 fprintf (out, "%s\n", prepend_specs[i]);
2215 if (prepend_count > 0)
2216 fputc ('\n', out);
de380723 2217
6c9c5c1f 2218 if (! stubs)
e04a16fb 2219 {
239b7dea
MM
2220 if (! print_cxx_classname (out, "class ", jcf,
2221 jcf->this_class, 0))
6c9c5c1f 2222 {
0237b2dc 2223 error ("class is of array type\n");
6c9c5c1f
AG
2224 return;
2225 }
2226 if (jcf->super_class)
2227 {
2228 if (! print_cxx_classname (out, " : public ",
239b7dea 2229 jcf, jcf->super_class, 1))
6c9c5c1f 2230 {
0237b2dc 2231 error ("base class is of array type");
6c9c5c1f
AG
2232 return;
2233 }
2234 }
2235
2236 fputs ("\n{\n", out);
e04a16fb
AG
2237 }
2238 }
e04a16fb 2239
bdb59aec 2240 /* Now go back for second pass over methods and fields. */
68566610
AH
2241 is_first_data_member = 1;
2242
bdb59aec
TT
2243 JCF_SEEK (jcf, method_start);
2244 method_pass = 1;
e04a16fb 2245 jcf_parse_methods (jcf);
e4de5a10
PB
2246 method_end = JCF_TELL (jcf);
2247
2248 field_pass = 1;
2249 JCF_SEEK (jcf, field_start);
2250 jcf_parse_fields (jcf);
2251 JCF_SEEK (jcf, method_end);
2252
e04a16fb
AG
2253 jcf_parse_final_attributes (jcf);
2254
de380723 2255 if (out && ! stubs)
fc45c7ef 2256 {
de380723 2257 if (flag_jni)
6c9c5c1f 2258 {
e0a0c416
TT
2259 fprintf (out, "\n#ifdef __cplusplus\n");
2260 fprintf (out, "}\n");
2261 fprintf (out, "#endif\n");
6c9c5c1f 2262 }
de380723
TT
2263 else
2264 {
2265 /* Generate friend decl if we still must. */
2266 for (i = 0; i < friend_count; ++i)
2267 fprintf (out, " friend %s\n", friend_specs[i]);
2268
2269 /* Generate extra declarations. */
2270 if (add_count > 0)
2271 fputc ('\n', out);
2272 for (i = 0; i < add_count; ++i)
2273 fprintf (out, " %s\n", add_specs[i]);
2274
e0a0c416
TT
2275 /* Generate an entry for the class object. */
2276 generate_access (out, ACC_PUBLIC);
2277 fprintf (out, "\n static ::java::lang::Class class$;\n");
2278
60c87482
BM
2279 fputs ("}", out);
2280
2281 if (jcf->access_flags & ACC_INTERFACE)
2282 fputs (" __attribute__ ((java_interface))", out);
2283
2284 fputs (";\n", out);
de380723
TT
2285
2286 if (append_count > 0)
2287 fputc ('\n', out);
2288 for (i = 0; i < append_count; ++i)
2289 fprintf (out, "%s\n", append_specs[i]);
2290 }
2291
2292 print_mangled_classname (out, jcf,
2293 "\n#endif /* __", jcf->this_class);
2294 fprintf (out, "__ */\n");
fc45c7ef 2295 }
e04a16fb
AG
2296}
2297
c89c53eb
TT
2298\f
2299
2300/* This is used to mark options with no short value. */
2301#define LONG_OPT(Num) ((Num) + 128)
2302
db444fbe 2303#define OPT_classpath LONG_OPT (0)
2a85660d
PB
2304#define OPT_CLASSPATH OPT_classpath
2305#define OPT_bootclasspath LONG_OPT (1)
9fef1fe3
AG
2306#define OPT_extdirs LONG_OPT (2)
2307#define OPT_HELP LONG_OPT (3)
2308#define OPT_TEMP LONG_OPT (4)
2309#define OPT_VERSION LONG_OPT (5)
2310#define OPT_PREPEND LONG_OPT (6)
2311#define OPT_FRIEND LONG_OPT (7)
2312#define OPT_ADD LONG_OPT (8)
2313#define OPT_APPEND LONG_OPT (9)
2314#define OPT_M LONG_OPT (10)
2315#define OPT_MM LONG_OPT (11)
2316#define OPT_MG LONG_OPT (12)
2317#define OPT_MD LONG_OPT (13)
2318#define OPT_MMD LONG_OPT (14)
d8be0aab
TF
2319#define OPT_FORCE LONG_OPT (15)
2320#define OPT_OLD LONG_OPT (16)
2321#define OPT_TRACE LONG_OPT (17)
c89c53eb 2322
c083a819 2323static const struct option options[] =
c89c53eb 2324{
db444fbe 2325 { "classpath", required_argument, NULL, OPT_classpath },
2a85660d 2326 { "bootclasspath", required_argument, NULL, OPT_bootclasspath },
9fef1fe3 2327 { "extdirs", required_argument, NULL, OPT_extdirs },
db444fbe
NF
2328 { "CLASSPATH", required_argument, NULL, OPT_CLASSPATH },
2329 { "help", no_argument, NULL, OPT_HELP },
2330 { "stubs", no_argument, &stubs, 1 },
2331 { "td", required_argument, NULL, OPT_TEMP },
2332 { "verbose", no_argument, NULL, 'v' },
2333 { "version", no_argument, NULL, OPT_VERSION },
2334 { "prepend", required_argument, NULL, OPT_PREPEND },
2335 { "friend", required_argument, NULL, OPT_FRIEND },
2336 { "add", required_argument, NULL, OPT_ADD },
2337 { "append", required_argument, NULL, OPT_APPEND },
2338 { "M", no_argument, NULL, OPT_M },
2339 { "MM", no_argument, NULL, OPT_MM },
2340 { "MG", no_argument, NULL, OPT_MG },
2341 { "MD", no_argument, NULL, OPT_MD },
2342 { "MMD", no_argument, NULL, OPT_MMD },
2343 { "jni", no_argument, &flag_jni, 1 },
d8be0aab
TF
2344 { "force", no_argument, NULL, OPT_FORCE },
2345 /* If the output file should be named "ld" then a space is needed
2346 between -o and its argument, ld. */
2347 { "old", no_argument, NULL, OPT_OLD },
2348 { "trace", no_argument, NULL, OPT_TRACE },
2349 { NULL, required_argument, NULL, 'J' },
db444fbe 2350 { NULL, no_argument, NULL, 0 }
c89c53eb
TT
2351};
2352
e04a16fb 2353static void
0a2f0c54 2354usage (void)
e04a16fb 2355{
d8be0aab 2356 fprintf (stderr, _("Try '" TOOLNAME " --help' for more information.\n"));
e04a16fb
AG
2357 exit (1);
2358}
2359
2360static void
0a2f0c54 2361help (void)
e04a16fb 2362{
d8be0aab
TF
2363 printf (_("Usage: " TOOLNAME " [OPTION]... CLASS...\n\n"));
2364 printf (_("Generate C or C++ header files from .class files\n\n"));
0237b2dc
JM
2365 printf (_(" -stubs Generate an implementation stub file\n"));
2366 printf (_(" -jni Generate a JNI header or stub\n"));
d8be0aab
TF
2367 printf (_(" -force Always overwrite output files\n"));
2368 printf (_(" -old Unused compatibility option\n"));
2369 printf (_(" -trace Unused compatibility option\n"));
2370 printf (_(" -J OPTION Unused compatibility option\n"));
c89c53eb 2371 printf ("\n");
0237b2dc
JM
2372 printf (_(" -add TEXT Insert TEXT into class body\n"));
2373 printf (_(" -append TEXT Insert TEXT after class declaration\n"));
597cdf4f 2374 printf (_(" -friend TEXT Insert TEXT as 'friend' declaration\n"));
0237b2dc 2375 printf (_(" -prepend TEXT Insert TEXT before start of class\n"));
c89c53eb 2376 printf ("\n");
0237b2dc
JM
2377 printf (_(" --classpath PATH Set path to find .class files\n"));
2378 printf (_(" -IDIR Append directory to class path\n"));
2379 printf (_(" --bootclasspath PATH Override built-in class path\n"));
2380 printf (_(" --extdirs PATH Set extensions directory path\n"));
2381 printf (_(" -d DIRECTORY Set output directory name\n"));
2382 printf (_(" -o FILE Set output file name\n"));
2383 printf (_(" -td DIRECTORY Set temporary directory name\n"));
c89c53eb 2384 printf ("\n");
0237b2dc
JM
2385 printf (_(" --help Print this help, then exit\n"));
2386 printf (_(" --version Print version number, then exit\n"));
2387 printf (_(" -v, --verbose Print extra information while running\n"));
c89c53eb 2388 printf ("\n");
0237b2dc
JM
2389 printf (_(" -M Print all dependencies to stdout;\n"
2390 " suppress ordinary output\n"));
2391 printf (_(" -MM Print non-system dependencies to stdout;\n"
2392 " suppress ordinary output\n"));
2393 printf (_(" -MD Print all dependencies to stdout\n"));
2394 printf (_(" -MMD Print non-system dependencies to stdout\n"));
c89c53eb
TT
2395 /* We omit -MG until it is implemented. */
2396 printf ("\n");
0237b2dc
JM
2397 printf (_("For bug reporting instructions, please see:\n"
2398 "%s.\n"), bug_report_url);
e04a16fb
AG
2399 exit (0);
2400}
2401
e04a16fb 2402static void
0a2f0c54 2403version (void)
e04a16fb 2404{
d8be0aab 2405 printf (TOOLNAME " (GCC) %s\n\n", version_string);
a6d6c2c0 2406 printf ("Copyright %s 2006 Free Software Foundation, Inc.\n", _("(C)"));
0237b2dc
JM
2407 printf (_("This is free software; see the source for copying conditions. There is NO\n"
2408 "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"));
e04a16fb
AG
2409 exit (0);
2410}
2411
2412int
6ff2fe39 2413main (int argc, char** argv)
e04a16fb
AG
2414{
2415 JCF jcf;
2416 int argi;
fc45c7ef
TT
2417 char *output_file = NULL;
2418 int emit_dependencies = 0, suppress_output = 0;
c89c53eb 2419 int opt;
a67aa338 2420 int local_found_error;
e04a16fb 2421
98a3dad4 2422 /* Unlock the stdio streams. */
2653bb0c 2423 unlock_std_streams ();
98a3dad4 2424
0237b2dc
JM
2425 gcc_init_libintl ();
2426
e04a16fb 2427 if (argc <= 1)
c89c53eb 2428 {
0237b2dc 2429 error ("no classes specified");
c89c53eb
TT
2430 usage ();
2431 }
e04a16fb 2432
8603f9c5
TT
2433 jcf_path_init ();
2434
c89c53eb
TT
2435 /* We use getopt_long_only to allow single `-' long options. For
2436 some of our options this is more natural. */
d8be0aab 2437 while ((opt = getopt_long_only (argc, argv, "J:I:d:o:v", options, NULL)) != -1)
e04a16fb 2438 {
c89c53eb
TT
2439 switch (opt)
2440 {
2441 case 0:
2442 /* Already handled. */
2443 break;
e04a16fb 2444
c89c53eb
TT
2445 case 'o':
2446 output_file = optarg;
2447 break;
e04a16fb 2448
c89c53eb
TT
2449 case 'd':
2450 output_directory = optarg;
2451 break;
e04a16fb 2452
c89c53eb
TT
2453 case 'I':
2454 jcf_path_include_arg (optarg);
2455 break;
2456
2457 case 'v':
2458 verbose++;
2459 break;
2460
2461 case OPT_classpath:
2462 jcf_path_classpath_arg (optarg);
2463 break;
2464
2a85660d
PB
2465 case OPT_bootclasspath:
2466 jcf_path_bootclasspath_arg (optarg);
c89c53eb
TT
2467 break;
2468
9fef1fe3
AG
2469 case OPT_extdirs:
2470 jcf_path_extdirs_arg (optarg);
2471 break;
2472
c89c53eb
TT
2473 case OPT_HELP:
2474 help ();
2475 break;
2476
2477 case OPT_TEMP:
2478 temp_directory = optarg;
2479 break;
2480
2481 case OPT_VERSION:
2482 version ();
2483 break;
2484
2485 case OPT_PREPEND:
2486 if (prepend_count == 0)
5ed6ace5 2487 prepend_specs = XNEWVEC (char *, argc);
c89c53eb
TT
2488 prepend_specs[prepend_count++] = optarg;
2489 break;
2490
2491 case OPT_FRIEND:
2492 if (friend_count == 0)
5ed6ace5 2493 friend_specs = XNEWVEC (char *, argc);
c89c53eb
TT
2494 friend_specs[friend_count++] = optarg;
2495 break;
2496
2497 case OPT_ADD:
2498 if (add_count == 0)
5ed6ace5 2499 add_specs = XNEWVEC (char *, argc);
c89c53eb
TT
2500 add_specs[add_count++] = optarg;
2501 break;
2502
2503 case OPT_APPEND:
2504 if (append_count == 0)
5ed6ace5 2505 append_specs = XNEWVEC (char *, argc);
c89c53eb
TT
2506 append_specs[append_count++] = optarg;
2507 break;
2508
2509 case OPT_M:
fc45c7ef
TT
2510 emit_dependencies = 1;
2511 suppress_output = 1;
2512 jcf_dependency_init (1);
c89c53eb
TT
2513 break;
2514
2515 case OPT_MM:
fc45c7ef
TT
2516 emit_dependencies = 1;
2517 suppress_output = 1;
2518 jcf_dependency_init (0);
c89c53eb
TT
2519 break;
2520
2521 case OPT_MG:
597cdf4f 2522 error ("'-MG' option is unimplemented");
fc45c7ef 2523 exit (1);
c89c53eb
TT
2524
2525 case OPT_MD:
fc45c7ef
TT
2526 emit_dependencies = 1;
2527 jcf_dependency_init (1);
c89c53eb
TT
2528 break;
2529
2530 case OPT_MMD:
fc45c7ef
TT
2531 emit_dependencies = 1;
2532 jcf_dependency_init (0);
c89c53eb
TT
2533 break;
2534
d8be0aab
TF
2535 case OPT_FORCE:
2536 break;
2537
2538 case OPT_OLD:
2539 break;
2540
2541 case OPT_TRACE:
2542 break;
2543
2544 case 'J':
2545 /* Ignore -J options. */
2546 break;
2547
c89c53eb
TT
2548 default:
2549 usage ();
2550 break;
e04a16fb
AG
2551 }
2552 }
2553
c89c53eb
TT
2554 if (optind == argc)
2555 {
0237b2dc 2556 error ("no classes specified");
c89c53eb
TT
2557 usage ();
2558 }
e04a16fb 2559
4266d0b2 2560 jcf_path_seal (verbose);
8603f9c5 2561
fc45c7ef
TT
2562 if (output_file && emit_dependencies)
2563 {
0237b2dc 2564 error ("can't specify both -o and -MD");
fc45c7ef
TT
2565 exit (1);
2566 }
2567
a67aa338 2568 local_found_error = 0;
c89c53eb 2569 for (argi = optind; argi < argc; argi++)
e04a16fb
AG
2570 {
2571 char *classname = argv[argi];
a67aa338 2572 char *current_output_file = NULL;
c8e7d2e6 2573 const char *classfile_name;
e04a16fb 2574
a67aa338
TT
2575 /* We reset the error state here so that we can detect errors
2576 that occur when processing this file, so the output can be
2577 unlinked if need be. */
2578 found_error = 0;
2579
e04a16fb 2580 if (verbose)
0237b2dc 2581 printf (_("Processing %s\n"), classname);
fc45c7ef
TT
2582 if (! output_file)
2583 jcf_dependency_reset ();
4cc4a45b 2584 classfile_name = find_class (classname, strlen (classname), &jcf, 0);
e04a16fb
AG
2585 if (classfile_name == NULL)
2586 {
0237b2dc 2587 error ("%s: no such class", classname);
e04a16fb
AG
2588 exit (1);
2589 }
2590 if (verbose)
0237b2dc 2591 printf (_("Found in %s\n"), classfile_name);
e04a16fb
AG
2592 if (output_file)
2593 {
2594 if (strcmp (output_file, "-") == 0)
2595 out = stdout;
2596 else if (out == NULL)
fc45c7ef
TT
2597 {
2598 out = fopen (output_file, "w");
2599 }
e04a16fb
AG
2600 if (out == NULL)
2601 {
2602 perror (output_file);
2603 exit (1);
2604 }
2605 current_output_file = output_file;
2606 }
2607 else
2608 {
2609 int dir_len = strlen (output_directory);
2610 int i, classname_length = strlen (classname);
5ed6ace5 2611 current_output_file = XNEWVEC (char, dir_len + classname_length + 5);
e04a16fb
AG
2612 strcpy (current_output_file, output_directory);
2613 if (dir_len > 0 && output_directory[dir_len-1] != '/')
2614 current_output_file[dir_len++] = '/';
2615 for (i = 0; classname[i] != '\0'; i++)
2616 {
2617 char ch = classname[i];
2618 if (ch == '.')
2619 ch = '/';
de380723
TT
2620 if (flag_jni && ch == '/')
2621 ch = '_';
e04a16fb
AG
2622 current_output_file[dir_len++] = ch;
2623 }
fc45c7ef 2624 if (emit_dependencies)
e04a16fb 2625 {
fc45c7ef
TT
2626 if (suppress_output)
2627 {
2628 jcf_dependency_set_dep_file ("-");
2629 out = NULL;
2630 }
2631 else
2632 {
2633 /* We use `.hd' and not `.d' to avoid clashes with
2634 dependency tracking from straight compilation. */
2635 strcpy (current_output_file + dir_len, ".hd");
2636 jcf_dependency_set_dep_file (current_output_file);
2637 }
2638 }
6c9c5c1f 2639 strcpy (current_output_file + dir_len,
de380723 2640 stubs ? (flag_jni ? ".c" : ".cc") : ".h");
fc45c7ef
TT
2641 jcf_dependency_set_target (current_output_file);
2642 if (! suppress_output)
2643 {
2644 out = fopen (current_output_file, "w");
2645 if (out == NULL)
2646 {
2647 perror (current_output_file);
2648 exit (1);
2649 }
e04a16fb
AG
2650 }
2651 }
b8b639c9 2652 free_method_name_list ();
e04a16fb
AG
2653 process_file (&jcf, out);
2654 JCF_FINISH (&jcf);
a67aa338
TT
2655
2656 /* If we found an error and we're writing to a real file,
2657 delete it. */
2658 if (found_error && ! suppress_output && current_output_file != NULL
2659 && strcmp (current_output_file, "-"))
2660 unlink (current_output_file);
2661
e04a16fb
AG
2662 if (current_output_file != output_file)
2663 free (current_output_file);
fc45c7ef 2664 jcf_dependency_write ();
a67aa338
TT
2665
2666 local_found_error |= found_error;
e04a16fb
AG
2667 }
2668
2669 if (out != NULL && out != stdout)
2670 fclose (out);
2671
a67aa338 2672 return local_found_error;
e04a16fb 2673}
This page took 2.986051 seconds and 5 git commands to generate.