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