OSDN Git Service

* collect2.c (is_ctor_dtor): Const-ify.
[pf3gnuchains/gcc-fork.git] / gcc / java / lex.c
1 /* Language lexer for the GNU compiler for the Java(TM) language.
2    Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
3    Contributed by Alexandre Petit-Bianco (apbianco@cygnus.com)
4
5 This file is part of GNU CC.
6
7 GNU CC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 GNU CC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GNU CC; see the file COPYING.  If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. 
21
22 Java and all Java-based marks are trademarks or registered trademarks
23 of Sun Microsystems, Inc. in the United States and other countries.
24 The Free Software Foundation is independent of Sun Microsystems, Inc.  */
25
26 /* It defines java_lex (yylex) that reads a Java ASCII source file
27    possibly containing Unicode escape sequence or utf8 encoded
28    characters and returns a token for everything found but comments,
29    white spaces and line terminators. When necessary, it also fills
30    the java_lval (yylval) union. It's implemented to be called by a
31    re-entrant parser generated by Bison.
32
33    The lexical analysis conforms to the Java grammar described in "The
34    Java(TM) Language Specification. J. Gosling, B. Joy, G. Steele.
35    Addison Wesley 1996" (http://java.sun.com/docs/books/jls/html/3.doc.html) */
36
37 #include "keyword.h"
38 #include "flags.h"
39 #include "chartables.h"
40
41 /* Function declaration  */
42 static char *java_sprint_unicode PARAMS ((struct java_line *, int));
43 static void java_unicode_2_utf8 PARAMS ((unicode_t));
44 static void java_lex_error PARAMS ((const char *, int));
45 #ifndef JC1_LITE
46 static int java_is_eol PARAMS ((FILE *, int));
47 static tree build_wfl_node PARAMS ((tree));
48 #endif
49 static void java_store_unicode PARAMS ((struct java_line *, unicode_t, int));
50 static int java_parse_escape_sequence PARAMS ((void));
51 static int java_start_char_p PARAMS ((unicode_t));
52 static int java_part_char_p PARAMS ((unicode_t));
53 static int java_parse_doc_section PARAMS ((int));
54 static void java_parse_end_comment PARAMS ((int));
55 static int java_get_unicode PARAMS ((void));
56 static int java_read_unicode PARAMS ((java_lexer *, int *));
57 static int java_read_unicode_collapsing_terminators PARAMS ((java_lexer *,
58                                                              int *));
59 static void java_store_unicode PARAMS ((struct java_line *, unicode_t, int));
60 static int java_read_char PARAMS ((java_lexer *));
61 static void java_allocate_new_line PARAMS ((void));
62 static void java_unget_unicode PARAMS ((void));
63 static unicode_t java_sneak_unicode PARAMS ((void));
64 #ifndef JC1_LITE
65 static int utf8_cmp PARAMS ((const unsigned char *, int, const char *));
66 #endif
67
68 java_lexer *java_new_lexer PARAMS ((FILE *, const char *));
69 #ifndef JC1_LITE
70 static void error_if_numeric_overflow PARAMS ((tree));
71 #endif
72
73 #ifdef HAVE_ICONV
74 /* This is nonzero if we have initialized `need_byteswap'.  */
75 static int byteswap_init = 0;
76
77 /* Some versions of iconv() (e.g., glibc 2.1.3) will return UCS-2 in
78    big-endian order -- not native endian order.  We handle this by
79    doing a conversion once at startup and seeing what happens.  This
80    flag holds the results of this determination.  */
81 static int need_byteswap = 0;
82 #endif
83
84 void
85 java_init_lex (finput, encoding)
86      FILE *finput;
87      const char *encoding;
88 {
89 #ifndef JC1_LITE
90   int java_lang_imported = 0;
91
92   if (!java_lang_id)
93     java_lang_id = get_identifier ("java.lang");
94   if (!java_lang_cloneable)
95     java_lang_cloneable = get_identifier ("java.lang.Cloneable");
96   if (!java_io_serializable)
97     java_io_serializable = get_identifier ("java.io.Serializable");
98   if (!inst_id)
99     inst_id = get_identifier ("inst$");
100   if (!wpv_id)
101     wpv_id = get_identifier ("write_parm_value$");
102
103   if (!java_lang_imported)
104     {
105       tree node = build_tree_list 
106         (build_expr_wfl (java_lang_id, NULL, 0, 0), NULL_TREE);
107       read_import_dir (TREE_PURPOSE (node));
108       TREE_CHAIN (node) = ctxp->import_demand_list;
109       ctxp->import_demand_list = node;
110       java_lang_imported = 1;
111     }
112
113   if (!wfl_operator)
114     wfl_operator = build_expr_wfl (NULL_TREE, ctxp->filename, 0, 0);
115   if (!label_id)
116     label_id = get_identifier ("$L");
117   if (!wfl_append) 
118     wfl_append = build_expr_wfl (get_identifier ("append"), NULL, 0, 0);
119   if (!wfl_string_buffer)
120     wfl_string_buffer = 
121       build_expr_wfl (get_identifier (flag_emit_class_files
122                                       ? "java.lang.StringBuffer"
123                                       : "gnu.gcj.runtime.StringBuffer"),
124                       NULL, 0, 0);
125   if (!wfl_to_string)
126     wfl_to_string = build_expr_wfl (get_identifier ("toString"), NULL, 0, 0);
127
128   CPC_INITIALIZER_LIST (ctxp) = CPC_STATIC_INITIALIZER_LIST (ctxp) =
129     CPC_INSTANCE_INITIALIZER_LIST (ctxp) = NULL_TREE;
130
131   memset ((PTR) ctxp->modifier_ctx, 0, 11*sizeof (ctxp->modifier_ctx[0]));
132   memset ((PTR) current_jcf, 0, sizeof (JCF));
133   ctxp->current_parsed_class = NULL;
134   ctxp->package = NULL_TREE;
135 #endif
136
137   ctxp->filename = input_filename;
138   ctxp->lineno = lineno = 0;
139   ctxp->p_line = NULL;
140   ctxp->c_line = NULL;
141   ctxp->java_error_flag = 0;
142   ctxp->lexer = java_new_lexer (finput, encoding);
143 }
144
145 static char *
146 java_sprint_unicode (line, i)
147     struct java_line *line;
148     int i;
149 {
150   static char buffer [10];
151   if (line->unicode_escape_p [i] || line->line [i] > 128)
152     sprintf (buffer, "\\u%04x", line->line [i]);
153   else
154     {
155       buffer [0] = line->line [i];
156       buffer [1] = '\0';
157     }
158   return buffer;
159 }
160
161 static unicode_t
162 java_sneak_unicode ()
163 {
164   return (ctxp->c_line->line [ctxp->c_line->current]);
165 }
166
167 static void
168 java_unget_unicode ()
169 {
170   if (!ctxp->c_line->current)
171     /* Can't unget unicode.  */
172     abort ();
173
174   ctxp->c_line->current--;
175   ctxp->c_line->char_col -= JAVA_COLUMN_DELTA (0);
176 }
177
178 static void
179 java_allocate_new_line ()
180 {
181   unicode_t ahead = (ctxp->c_line ? ctxp->c_line->ahead[0] : '\0');
182   char ahead_escape_p = (ctxp->c_line ? 
183                          ctxp->c_line->unicode_escape_ahead_p : 0);
184
185   if (ctxp->c_line && !ctxp->c_line->white_space_only)
186     {
187       if (ctxp->p_line)
188         {
189           free (ctxp->p_line->unicode_escape_p);
190           free (ctxp->p_line->line);
191           free (ctxp->p_line);
192         }
193       ctxp->p_line = ctxp->c_line;
194       ctxp->c_line = NULL;              /* Reallocated */
195     }
196
197   if (!ctxp->c_line)
198     {
199       ctxp->c_line = (struct java_line *)xmalloc (sizeof (struct java_line));
200       ctxp->c_line->max = JAVA_LINE_MAX;
201       ctxp->c_line->line = (unicode_t *)xmalloc 
202         (sizeof (unicode_t)*ctxp->c_line->max);
203       ctxp->c_line->unicode_escape_p = 
204           (char *)xmalloc (sizeof (char)*ctxp->c_line->max);
205       ctxp->c_line->white_space_only = 0;
206     }
207
208   ctxp->c_line->line [0] = ctxp->c_line->size = 0;
209   ctxp->c_line->char_col = ctxp->c_line->current = 0;
210   if (ahead)
211     {
212       ctxp->c_line->line [ctxp->c_line->size] = ahead;
213       ctxp->c_line->unicode_escape_p [ctxp->c_line->size] = ahead_escape_p;
214       ctxp->c_line->size++;
215     }
216   ctxp->c_line->ahead [0] = 0;
217   ctxp->c_line->unicode_escape_ahead_p = 0;
218   ctxp->c_line->lineno = ++lineno;
219   ctxp->c_line->white_space_only = 1;
220 }
221
222 /* Create a new lexer object.  */
223
224 java_lexer *
225 java_new_lexer (finput, encoding)
226      FILE *finput;
227      const char *encoding;
228 {
229   java_lexer *lex = (java_lexer *) xmalloc (sizeof (java_lexer));
230   int enc_error = 0;
231
232   lex->finput = finput;
233   lex->bs_count = 0;
234   lex->unget_value = 0;
235   lex->hit_eof = 0;
236
237 #ifdef HAVE_ICONV
238   lex->handle = iconv_open ("UCS-2", encoding);
239   if (lex->handle != (iconv_t) -1)
240     {
241       lex->first = -1;
242       lex->last = -1;
243       lex->out_first = -1;
244       lex->out_last = -1;
245       lex->read_anything = 0;
246       lex->use_fallback = 0;
247
248       /* Work around broken iconv() implementations by doing checking at
249          runtime.  We assume that if the UTF-8 => UCS-2 encoder is broken,
250          then all UCS-2 encoders will be broken.  Perhaps not a valid
251          assumption.  */
252       if (! byteswap_init)
253         {
254           iconv_t handle;
255
256           byteswap_init = 1;
257
258           handle = iconv_open ("UCS-2", "UTF-8");
259           if (handle != (iconv_t) -1)
260             {
261               unicode_t result;
262               unsigned char in[3];
263               char *inp, *outp;
264               size_t inc, outc, r;
265
266               /* This is the UTF-8 encoding of \ufeff.  */
267               in[0] = 0xef;
268               in[1] = 0xbb;
269               in[2] = 0xbf;
270
271               inp = in;
272               inc = 3;
273               outp = (char *) &result;
274               outc = 2;
275
276               r = iconv (handle, (ICONV_CONST char **) &inp, &inc,
277                          &outp, &outc);
278               iconv_close (handle);
279               /* Conversion must be complete for us to use the result.  */
280               if (r != (size_t) -1 && inc == 0 && outc == 0)
281                 need_byteswap = (result != 0xfeff);
282             }
283         }
284
285       lex->byte_swap = need_byteswap;
286     }
287   else
288 #endif /* HAVE_ICONV */
289     {
290       /* If iconv failed, use the internal decoder if the default
291          encoding was requested.  This code is used on platforms where
292          iconv exists but is insufficient for our needs.  For
293          instance, on Solaris 2.5 iconv cannot handle UTF-8 or UCS-2.  */
294       if (strcmp (encoding, DEFAULT_ENCODING))
295         enc_error = 1;
296 #ifdef HAVE_ICONV
297       else
298         lex->use_fallback = 1;
299 #endif /* HAVE_ICONV */
300     }
301
302   if (enc_error)
303     fatal_error ("unknown encoding: `%s'\nThis might mean that your locale's encoding is not supported\nby your system's iconv(3) implementation.  If you aren't trying\nto use a particular encoding for your input file, try the\n`--encoding=UTF-8' option", encoding);
304
305   return lex;
306 }
307
308 void
309 java_destroy_lexer (lex)
310      java_lexer *lex;
311 {
312 #ifdef HAVE_ICONV
313   if (! lex->use_fallback)
314     iconv_close (lex->handle);
315 #endif
316   free (lex);
317 }
318
319 static int
320 java_read_char (lex)
321      java_lexer *lex;
322 {
323   if (lex->unget_value)
324     {
325       unicode_t r = lex->unget_value;
326       lex->unget_value = 0;
327       return r;
328     }
329
330 #ifdef HAVE_ICONV
331   if (! lex->use_fallback)
332     {
333       size_t ir, inbytesleft, in_save, out_count, out_save;
334       char *inp, *outp;
335       unicode_t result;
336
337       /* If there is data which has already been converted, use it.  */
338       if (lex->out_first == -1 || lex->out_first >= lex->out_last)
339         {
340           lex->out_first = 0;
341           lex->out_last = 0;
342
343           while (1)
344             {
345               /* See if we need to read more data.  If FIRST == 0 then
346                  the previous conversion attempt ended in the middle of
347                  a character at the end of the buffer.  Otherwise we
348                  only have to read if the buffer is empty.  */
349               if (lex->first == 0 || lex->first >= lex->last)
350                 {
351                   int r;
352
353                   if (lex->first >= lex->last)
354                     {
355                       lex->first = 0;
356                       lex->last = 0;
357                     }
358                   if (feof (lex->finput))
359                     return UEOF;
360                   r = fread (&lex->buffer[lex->last], 1,
361                              sizeof (lex->buffer) - lex->last,
362                              lex->finput);
363                   lex->last += r;
364                 }
365
366               inbytesleft = lex->last - lex->first;
367               out_count = sizeof (lex->out_buffer) - lex->out_last;
368
369               if (inbytesleft == 0)
370                 {
371                   /* We've tried to read and there is nothing left.  */
372                   return UEOF;
373                 }
374
375               in_save = inbytesleft;
376               out_save = out_count;
377               inp = &lex->buffer[lex->first];
378               outp = &lex->out_buffer[lex->out_last];
379               ir = iconv (lex->handle, (ICONV_CONST char **) &inp,
380                           &inbytesleft, &outp, &out_count);
381
382               /* If we haven't read any bytes, then look to see if we
383                  have read a BOM.  */
384               if (! lex->read_anything && out_save - out_count >= 2)
385                 {
386                   unicode_t uc = * (unicode_t *) &lex->out_buffer[0];
387                   if (uc == 0xfeff)
388                     {
389                       lex->byte_swap = 0;
390                       lex->out_first += 2;
391                     }
392                   else if (uc == 0xfffe)
393                     {
394                       lex->byte_swap = 1;
395                       lex->out_first += 2;
396                     }
397                   lex->read_anything = 1;
398                 }
399
400               if (lex->byte_swap)
401                 {
402                   unsigned int i;
403                   for (i = 0; i < out_save - out_count; i += 2)
404                     {
405                       char t = lex->out_buffer[lex->out_last + i];
406                       lex->out_buffer[lex->out_last + i]
407                         = lex->out_buffer[lex->out_last + i + 1];
408                       lex->out_buffer[lex->out_last + i + 1] = t;
409                     }
410                 }
411
412               lex->first += in_save - inbytesleft;
413               lex->out_last += out_save - out_count;
414
415               /* If we converted anything at all, move along.  */
416               if (out_count != out_save)
417                 break;
418
419               if (ir == (size_t) -1)
420                 {
421                   if (errno == EINVAL)
422                     {
423                       /* This is ok.  This means that the end of our buffer
424                          is in the middle of a character sequence.  We just
425                          move the valid part of the buffer to the beginning
426                          to force a read.  */
427                       memmove (&lex->buffer[0], &lex->buffer[lex->first],
428                                lex->last - lex->first);
429                       lex->last -= lex->first;
430                       lex->first = 0;
431                     }
432                   else
433                     {
434                       /* A more serious error.  */
435                       java_lex_error ("unrecognized character in input stream",
436                                       0);
437                       return UEOF;
438                     }
439                 }
440             }
441         }
442
443       if (lex->out_first == -1 || lex->out_first >= lex->out_last)
444         {
445           /* Don't have any data.  */
446           return UEOF;
447         }
448
449       /* Success.  */
450       result = * ((unicode_t *) &lex->out_buffer[lex->out_first]);
451       lex->out_first += 2;
452       return result;
453     }
454   else
455 #endif /* HAVE_ICONV */
456     {
457       int c, c1, c2;
458       c = getc (lex->finput);
459
460       if (c == EOF)
461         return UEOF;
462       if (c < 128)
463         return (unicode_t) c;
464       else
465         {
466           if ((c & 0xe0) == 0xc0)
467             {
468               c1 = getc (lex->finput);
469               if ((c1 & 0xc0) == 0x80)
470                 {
471                   unicode_t r = (unicode_t)(((c & 0x1f) << 6) + (c1 & 0x3f));
472                   /* Check for valid 2-byte characters.  We explicitly
473                      allow \0 because this encoding is common in the
474                      Java world.  */
475                   if (r == 0 || (r >= 0x80 && r <= 0x7ff))
476                     return r;
477                 }
478             }
479           else if ((c & 0xf0) == 0xe0)
480             {
481               c1 = getc (lex->finput);
482               if ((c1 & 0xc0) == 0x80)
483                 {
484                   c2 = getc (lex->finput);
485                   if ((c2 & 0xc0) == 0x80)
486                     {
487                       unicode_t r =  (unicode_t)(((c & 0xf) << 12) + 
488                                                  (( c1 & 0x3f) << 6)
489                                                  + (c2 & 0x3f));
490                       /* Check for valid 3-byte characters.
491                          Don't allow surrogate, \ufffe or \uffff.  */
492                       if (r >= 0x800 && r <= 0xffff
493                           && ! (r >= 0xd800 && r <= 0xdfff)
494                           && r != 0xfffe && r != 0xffff)
495                         return r;
496                     }
497                 }
498             }
499
500           /* We simply don't support invalid characters.  We also
501              don't support 4-, 5-, or 6-byte UTF-8 sequences, as these
502              cannot be valid Java characters.  */
503           java_lex_error ("malformed UTF-8 character", 0);
504         }
505     }
506
507   /* We only get here on error.  */
508   return UEOF;
509 }
510
511 static void
512 java_store_unicode (l, c, unicode_escape_p)
513     struct java_line *l;
514     unicode_t c;
515     int unicode_escape_p;
516 {
517   if (l->size == l->max)
518     {
519       l->max += JAVA_LINE_MAX;
520       l->line = (unicode_t *) xrealloc (l->line, sizeof (unicode_t)*l->max);
521       l->unicode_escape_p = (char *) xrealloc (l->unicode_escape_p, 
522                                                sizeof (char)*l->max);
523     }
524   l->line [l->size] = c;
525   l->unicode_escape_p [l->size++] = unicode_escape_p;
526 }
527
528 static int
529 java_read_unicode (lex, unicode_escape_p)
530      java_lexer *lex;
531      int *unicode_escape_p;
532 {
533   int c;
534
535   c = java_read_char (lex);
536   *unicode_escape_p = 0;
537
538   if (c != '\\')
539     {
540       lex->bs_count = 0;
541       return c;
542     }
543
544   ++lex->bs_count;
545   if ((lex->bs_count) % 2 == 1)
546     {
547       /* Odd number of \ seen.  */
548       c = java_read_char (lex);
549       if (c == 'u')
550         {
551           unicode_t unicode = 0;
552           int shift = 12;
553
554           /* Recognize any number of `u's in \u.  */
555           while ((c = java_read_char (lex)) == 'u')
556             ;
557
558           /* Unget the most recent character as it is not a `u'.  */
559           if (c == UEOF)
560             return UEOF;
561           lex->unget_value = c;
562
563           /* Next should be 4 hex digits, otherwise it's an error.
564              The hex value is converted into the unicode, pushed into
565              the Unicode stream.  */
566           for (shift = 12; shift >= 0; shift -= 4)
567             {
568               if ((c = java_read_char (lex)) == UEOF)
569                 return UEOF;
570               if (hex_p (c))
571                 unicode |= (unicode_t)(hex_value (c) << shift);
572               else
573                 java_lex_error ("Non hex digit in Unicode escape sequence", 0);
574             }
575           lex->bs_count = 0;
576           *unicode_escape_p = 1;
577           return unicode;
578         }
579       lex->unget_value = c;
580     }
581   return (unicode_t) '\\';
582 }
583
584 static int
585 java_read_unicode_collapsing_terminators (lex, unicode_escape_p)
586      java_lexer *lex;
587      int *unicode_escape_p;
588 {
589   int c = java_read_unicode (lex, unicode_escape_p);
590
591   if (c == '\r')
592     {
593       /* We have to read ahead to see if we got \r\n.  In that case we
594          return a single line terminator.  */
595       int dummy;
596       c = java_read_unicode (lex, &dummy);
597       if (c != '\n')
598         lex->unget_value = c;
599       /* In either case we must return a newline.  */
600       c = '\n';
601     }
602
603   return c;
604 }
605
606 static int
607 java_get_unicode ()
608 {
609   /* It's time to read a line when... */
610   if (!ctxp->c_line || ctxp->c_line->current == ctxp->c_line->size)
611     {
612       int c;
613       int found_chars = 0;
614
615       if (ctxp->lexer->hit_eof)
616         return UEOF;
617
618       java_allocate_new_line ();
619       if (ctxp->c_line->line[0] != '\n')
620         {
621           for (;;)
622             {
623               int unicode_escape_p;
624               c = java_read_unicode_collapsing_terminators (ctxp->lexer,
625                                                             &unicode_escape_p);
626               if (c != UEOF)
627                 {
628                   found_chars = 1;
629                   java_store_unicode (ctxp->c_line, c, unicode_escape_p);
630                   if (ctxp->c_line->white_space_only 
631                       && !JAVA_WHITE_SPACE_P (c)
632                       && c != '\n')
633                     ctxp->c_line->white_space_only = 0;
634                 }
635               if ((c == '\n') || (c == UEOF))
636                 break;
637             }
638
639           if (c == UEOF && ! found_chars)
640             {
641               ctxp->lexer->hit_eof = 1;
642               return UEOF;
643             }
644         }
645     }
646   ctxp->c_line->char_col += JAVA_COLUMN_DELTA (0);
647   JAVA_LEX_CHAR (ctxp->c_line->line [ctxp->c_line->current]);
648   return ctxp->c_line->line [ctxp->c_line->current++];
649 }
650
651 /* Parse the end of a C style comment.
652  * C is the first character following the '/' and '*'. */
653 static void
654 java_parse_end_comment (c)
655      int c;
656 {
657   for ( ;; c = java_get_unicode ())
658     {
659       switch (c)
660         {
661         case UEOF:
662           java_lex_error ("Comment not terminated at end of input", 0);
663           return;
664         case '*':
665           switch (c = java_get_unicode ())
666             {
667             case UEOF:
668               java_lex_error ("Comment not terminated at end of input", 0);
669               return;
670             case '/':
671               return;
672             case '*':   /* reparse only '*' */
673               java_unget_unicode ();
674             }
675         }
676     }
677 }
678
679 /* Parse the documentation section. Keywords must be at the beginning
680    of a documentation comment line (ignoring white space and any `*'
681    character). Parsed keyword(s): @DEPRECATED.  */
682
683 static int
684 java_parse_doc_section (c)
685      int c;
686 {
687   int valid_tag = 0, seen_star = 0;
688
689   while (JAVA_WHITE_SPACE_P (c) || (c == '*') || c == '\n')
690     {
691       switch (c)
692         {
693         case '*':
694           seen_star = 1;
695           break;
696         case '\n': /* ULT */
697           valid_tag = 1;
698         default:
699           seen_star = 0;
700         }
701       c = java_get_unicode();
702     }
703
704   if (c == UEOF)
705     java_lex_error ("Comment not terminated at end of input", 0);
706
707   if (seen_star && (c == '/'))
708     return 1;                   /* Goto step1 in caller */
709
710   /* We're parsing @deprecated */
711   if (valid_tag && (c == '@'))
712     {
713       char tag [11];
714       int  tag_index = 0;
715
716       while (tag_index < 10 && c != UEOF && c != ' ' && c != '\n')
717         {
718           c = java_get_unicode ();
719           tag [tag_index++] = c;
720         }
721
722       if (c == UEOF)
723         java_lex_error ("Comment not terminated at end of input", 0);
724       tag [tag_index] = '\0';
725
726       if (!strcmp (tag, "deprecated"))
727         ctxp->deprecated = 1;
728     }
729   java_unget_unicode ();
730   return 0;
731 }
732
733 /* Return true if C is a valid start character for a Java identifier.
734    This is only called if C >= 128 -- smaller values are handled
735    inline.  However, this function handles all values anyway.  */
736 static int
737 java_start_char_p (c)
738      unicode_t c;
739 {
740   unsigned int hi = c / 256;
741   const char *const page = type_table[hi];
742   unsigned long val = (unsigned long) page;
743   int flags;
744
745   if ((val & ~ (LETTER_PART | LETTER_START)) != 0)
746     flags = page[c & 255];
747   else
748     flags = val;
749
750   return flags & LETTER_START;
751 }
752
753 /* Return true if C is a valid part character for a Java identifier.
754    This is only called if C >= 128 -- smaller values are handled
755    inline.  However, this function handles all values anyway.  */
756 static int
757 java_part_char_p (c)
758      unicode_t c;
759 {
760   unsigned int hi = c / 256;
761   const char *const page = type_table[hi];
762   unsigned long val = (unsigned long) page;
763   int flags;
764
765   if ((val & ~ (LETTER_PART | LETTER_START)) != 0)
766     flags = page[c & 255];
767   else
768     flags = val;
769
770   return flags & LETTER_PART;
771 }
772
773 static int
774 java_parse_escape_sequence ()
775 {
776   unicode_t char_lit;
777   int c;
778
779   switch (c = java_get_unicode ())
780     {
781     case 'b':
782       return (unicode_t)0x8;
783     case 't':
784       return (unicode_t)0x9;
785     case 'n':
786       return (unicode_t)0xa;
787     case 'f':
788       return (unicode_t)0xc;
789     case 'r':
790       return (unicode_t)0xd;
791     case '"':
792       return (unicode_t)0x22;
793     case '\'':
794       return (unicode_t)0x27;
795     case '\\':
796       return (unicode_t)0x5c;
797     case '0': case '1': case '2': case '3': case '4':
798     case '5': case '6': case '7':
799       {
800         int octal_escape[3];
801         int octal_escape_index = 0;
802         int max = 3;
803         int i, shift;
804
805         for (; octal_escape_index < max && RANGE (c, '0', '7');
806              c = java_get_unicode ())
807           {
808             if (octal_escape_index == 0 && c > '3')
809               {
810                 /* According to the grammar, `\477' has a well-defined
811                    meaning -- it is `\47' followed by `7'.  */
812                 --max;
813               }
814             octal_escape [octal_escape_index++] = c;
815           }
816
817         java_unget_unicode ();
818
819         for (char_lit=0, i = 0, shift = 3*(octal_escape_index-1);
820              i < octal_escape_index; i++, shift -= 3)
821           char_lit |= (octal_escape [i] - '0') << shift;
822
823         return char_lit;
824       }
825     default:
826       java_lex_error ("Invalid character in escape sequence", 0);
827       return JAVA_CHAR_ERROR;
828     }
829 }
830
831 /* Isolate the code which may raise an arithmetic exception in its
832    own function.  */
833
834 #ifndef JC1_LITE
835 struct jpa_args
836 {
837   YYSTYPE *java_lval;
838   char *literal_token;
839   int fflag;
840   int number_beginning;
841 };
842
843 #ifdef REAL_ARITHMETIC
844 #define IS_ZERO(X) (ereal_cmp (X, dconst0) == 0)
845 #else
846 #define IS_ZERO(X) ((X) == 0)
847 #endif
848
849 static void java_perform_atof   PARAMS ((PTR));
850
851 static void
852 java_perform_atof (av)
853      PTR av;
854 {
855   struct jpa_args *a = (struct jpa_args *)av;
856   YYSTYPE *java_lval = a->java_lval;
857   int number_beginning = a->number_beginning;
858   REAL_VALUE_TYPE value;
859   tree type = (a->fflag ? FLOAT_TYPE_NODE : DOUBLE_TYPE_NODE);
860
861   SET_REAL_VALUE_ATOF (value,
862                        REAL_VALUE_ATOF (a->literal_token, TYPE_MODE (type)));
863
864   if (REAL_VALUE_ISINF (value) || REAL_VALUE_ISNAN (value))
865     {
866       JAVA_FLOAT_RANGE_ERROR ((a->fflag ? "float" : "double"));
867       value = DCONST0;
868     }
869   else if (IS_ZERO (value))
870     {
871       /* We check to see if the value is really 0 or if we've found an
872          underflow.  We do this in the most primitive imaginable way.  */
873       int really_zero = 1;
874       char *p = a->literal_token;
875       if (*p == '-')
876         ++p;
877       while (*p && *p != 'e' && *p != 'E')
878         {
879           if (*p != '0' && *p != '.')
880             {
881               really_zero = 0;
882               break;
883             }
884           ++p;
885         }
886       if (! really_zero)
887         {
888           int i = ctxp->c_line->current;
889           ctxp->c_line->current = number_beginning;
890           java_lex_error ("Floating point literal underflow", 0);
891           ctxp->c_line->current = i;
892         }
893     }
894
895   SET_LVAL_NODE_TYPE (build_real (type, value), type);
896 }
897 #endif
898
899 static int yylex                PARAMS ((YYSTYPE *));
900
901 static int
902 #ifdef JC1_LITE
903 yylex (java_lval)
904 #else
905 java_lex (java_lval)
906 #endif
907      YYSTYPE *java_lval;
908 {
909   int c;
910   unicode_t first_unicode;
911   int ascii_index, all_ascii;
912   char *string;
913
914   /* Translation of the Unicode escape in the raw stream of Unicode
915      characters. Takes care of line terminator.  */
916  step1:
917   /* Skip white spaces: SP, TAB and FF or ULT */ 
918   for (c = java_get_unicode ();
919        c == '\n' || JAVA_WHITE_SPACE_P (c); c = java_get_unicode ())
920     if (c == '\n')
921       {
922         ctxp->elc.line = ctxp->c_line->lineno;
923         ctxp->elc.col  = ctxp->c_line->char_col-2;
924       }
925
926   ctxp->elc.col = (ctxp->elc.col < 0 ? 0 : ctxp->elc.col);
927
928   if (c == 0x1a)                /* CTRL-Z */
929     {
930       if ((c = java_get_unicode ()) == UEOF)
931         return 0;               /* Ok here */
932       else
933         java_unget_unicode ();  /* Caught later, at the end of the function */
934     }
935   /* Handle EOF here */
936   if (c == UEOF)        /* Should probably do something here... */
937     return 0;
938
939   /* Take care of eventual comments.  */
940   if (c == '/')
941     {
942       switch (c = java_get_unicode ())
943         {
944         case '/':
945           for (;;)
946             {
947               c = java_get_unicode ();
948               if (c == UEOF)
949                 {
950                   /* It is ok to end a `//' comment with EOF, unless
951                      we're being pedantic.  */
952                   if (pedantic)
953                     java_lex_error ("Comment not terminated at end of input",
954                                     0);
955                   return 0;
956                 }
957               if (c == '\n')    /* ULT */
958                 goto step1;
959             }
960           break;
961
962         case '*':
963           if ((c = java_get_unicode ()) == '*')
964             {
965               if ((c = java_get_unicode ()) == '/')
966                 goto step1;     /* Empy documentation comment  */
967               else if (java_parse_doc_section (c))
968                 goto step1;
969             }
970
971           java_parse_end_comment ((c = java_get_unicode ()));
972           goto step1;
973           break;
974         default:
975           java_unget_unicode ();
976           c = '/';
977           break;
978         }
979     }
980
981   ctxp->elc.line = ctxp->c_line->lineno;
982   ctxp->elc.prev_col = ctxp->elc.col;
983   ctxp->elc.col = ctxp->c_line->char_col - JAVA_COLUMN_DELTA (-1);
984   if (ctxp->elc.col < 0)
985     abort ();
986
987   /* Numeric literals */
988   if (JAVA_ASCII_DIGIT (c) || (c == '.'))
989     {
990       /* This section of code is borrowed from gcc/c-lex.c  */
991 #define TOTAL_PARTS ((HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR) * 2 + 2)
992       int parts[TOTAL_PARTS];
993       HOST_WIDE_INT high, low;
994       /* End borrowed section  */
995       char literal_token [256];
996       int  literal_index = 0, radix = 10, long_suffix = 0, overflow = 0, bytes;
997       int  found_hex_digits = 0;
998       int  i;
999 #ifndef JC1_LITE
1000       int  number_beginning = ctxp->c_line->current;
1001       tree value;
1002 #endif
1003       
1004       /* We might have a . separator instead of a FP like .[0-9]* */
1005       if (c == '.')
1006         {
1007           unicode_t peep = java_sneak_unicode ();
1008
1009           if (!JAVA_ASCII_DIGIT (peep))
1010             {
1011               JAVA_LEX_SEP('.');
1012               BUILD_OPERATOR (DOT_TK);
1013             }
1014         }
1015
1016       for (i = 0; i < TOTAL_PARTS; i++)
1017         parts [i] = 0;
1018
1019       if (c == '0')
1020         {
1021           c = java_get_unicode ();
1022           if (c == 'x' || c == 'X')
1023             {
1024               radix = 16;
1025               c = java_get_unicode ();
1026             }
1027           else if (JAVA_ASCII_DIGIT (c))
1028             radix = 8;
1029           else if (c == '.')
1030             {
1031               /* Push the '.' back and prepare for a FP parsing... */
1032               java_unget_unicode ();
1033               c = '0';
1034             }
1035           else
1036             {
1037               /* We have a zero literal: 0, 0{f,F}, 0{d,D} */
1038               JAVA_LEX_LIT ("0", 10);
1039               switch (c)
1040                 {               
1041                 case 'L': case 'l':
1042                   SET_LVAL_NODE (long_zero_node);
1043                   return (INT_LIT_TK);
1044                 case 'f': case 'F':
1045                   SET_LVAL_NODE (float_zero_node);
1046                   return (FP_LIT_TK);
1047                 case 'd': case 'D':
1048                   SET_LVAL_NODE (double_zero_node);
1049                   return (FP_LIT_TK);
1050                 default:
1051                   java_unget_unicode ();
1052                   SET_LVAL_NODE (integer_zero_node);
1053                   return (INT_LIT_TK);
1054                 }
1055             }
1056         }
1057       /* Parse the first part of the literal, until we find something
1058          which is not a number.  */
1059       while ((radix == 10 && JAVA_ASCII_DIGIT (c)) ||
1060              (radix == 16 && JAVA_ASCII_HEXDIGIT (c)) ||
1061              (radix == 8  && JAVA_ASCII_OCTDIGIT (c)))
1062         {
1063           /* We store in a string (in case it turns out to be a FP) and in
1064              PARTS if we have to process a integer literal.  */
1065           int numeric = hex_value (c);
1066           int count;
1067
1068           /* Remember when we find a valid hexadecimal digit */
1069           if (radix == 16)
1070             found_hex_digits = 1;
1071
1072           literal_token [literal_index++] = c;
1073           /* This section of code if borrowed from gcc/c-lex.c  */
1074           for (count = 0; count < TOTAL_PARTS; count++)
1075             {
1076               parts[count] *= radix;
1077               if (count)
1078                 {
1079                   parts[count]   += (parts[count-1] >> HOST_BITS_PER_CHAR);
1080                   parts[count-1] &= (1 << HOST_BITS_PER_CHAR) - 1;
1081                 }
1082               else
1083                 parts[0] += numeric;
1084             }
1085           if (parts [TOTAL_PARTS-1] != 0)
1086             overflow = 1;
1087           /* End borrowed section.  */
1088           c = java_get_unicode ();
1089         }
1090
1091       /* If we have something from the FP char set but not a digit, parse
1092          a FP literal.  */
1093       if (JAVA_ASCII_FPCHAR (c) && !JAVA_ASCII_DIGIT (c))
1094         {
1095           int stage = 0;
1096           int seen_digit = (literal_index ? 1 : 0);
1097           int seen_exponent = 0;
1098           int fflag = 0;        /* 1 for {f,F}, 0 for {d,D}. FP literal are
1099                                    double unless specified. */
1100
1101           /* It is ok if the radix is 8 because this just means we've
1102              seen a leading `0'.  However, radix==16 is invalid.  */
1103           if (radix == 16)
1104             java_lex_error ("Can't express non-decimal FP literal", 0);
1105           radix = 10;
1106
1107           for (;;)
1108             {
1109               if (c == '.')
1110                 {
1111                   if (stage < 1)
1112                     {
1113                       stage = 1;
1114                       literal_token [literal_index++ ] = c;
1115                       c = java_get_unicode ();
1116                     }
1117                   else
1118                     java_lex_error ("Invalid character in FP literal", 0);
1119                 }
1120
1121               if (c == 'e' || c == 'E')
1122                 {
1123                   if (stage < 2)
1124                     {
1125                       /* {E,e} must have seen at list a digit */
1126                       if (!seen_digit)
1127                         java_lex_error ("Invalid FP literal", 0);
1128                       seen_digit = 0;
1129                       seen_exponent = 1;
1130                       stage = 2;
1131                       literal_token [literal_index++] = c;
1132                       c = java_get_unicode ();
1133                     }
1134                   else
1135                     java_lex_error ("Invalid character in FP literal", 0);
1136                 }
1137               if ( c == 'f' || c == 'F' || c == 'd' || c == 'D')
1138                 {
1139                   fflag = ((c == 'd') || (c == 'D')) ? 0 : 1;
1140                   stage = 4;    /* So we fall through */
1141                 }
1142
1143               if ((c=='-' || c =='+') && stage == 2)
1144                 {
1145                   stage = 3;
1146                   literal_token [literal_index++] = c;
1147                   c = java_get_unicode ();
1148                 }
1149
1150               if ((stage == 0 && JAVA_ASCII_FPCHAR (c)) ||
1151                   (stage == 1 && JAVA_ASCII_FPCHAR (c) && !(c == '.')) ||
1152                   (stage == 2 && (JAVA_ASCII_DIGIT (c) || JAVA_FP_PM (c))) ||
1153                   (stage == 3 && JAVA_ASCII_DIGIT (c)))
1154                 {
1155                   if (JAVA_ASCII_DIGIT (c))
1156                     seen_digit = 1;
1157                   literal_token [literal_index++ ] = c;
1158                   c = java_get_unicode ();
1159                 }
1160               else
1161                 {
1162 #ifndef JC1_LITE
1163                   struct jpa_args a;
1164 #endif
1165                   if (stage != 4) /* Don't push back fF/dD */
1166                     java_unget_unicode ();
1167                   
1168                   /* An exponent (if any) must have seen a digit.  */
1169                   if (seen_exponent && !seen_digit)
1170                     java_lex_error ("Invalid FP literal", 0);
1171
1172                   literal_token [literal_index] = '\0';
1173                   JAVA_LEX_LIT (literal_token, radix);
1174
1175 #ifndef JC1_LITE
1176                   a.literal_token = literal_token;
1177                   a.fflag = fflag;
1178                   a.java_lval = java_lval;
1179                   a.number_beginning = number_beginning;
1180                   if (do_float_handler (java_perform_atof, (PTR) &a))
1181                     return FP_LIT_TK;
1182
1183                   JAVA_FLOAT_RANGE_ERROR ((fflag ? "float" : "double"));
1184 #else
1185                   return FP_LIT_TK;
1186 #endif
1187                 }
1188             }
1189         } /* JAVA_ASCCI_FPCHAR (c) */
1190
1191       if (radix == 16 && ! found_hex_digits)
1192         java_lex_error
1193           ("0x must be followed by at least one hexadecimal digit", 0);
1194
1195       /* Here we get back to converting the integral literal.  */
1196       if (c == 'L' || c == 'l')
1197         long_suffix = 1;
1198       else if (radix == 16 && JAVA_ASCII_LETTER (c))
1199         java_lex_error ("Digit out of range in hexadecimal literal", 0);
1200       else if (radix == 8  && JAVA_ASCII_DIGIT (c))
1201         java_lex_error ("Digit out of range in octal literal", 0);
1202       else if (radix == 16 && !literal_index)
1203         java_lex_error ("No digit specified for hexadecimal literal", 0);
1204       else
1205         java_unget_unicode ();
1206
1207 #ifdef JAVA_LEX_DEBUG
1208       literal_token [literal_index] = '\0'; /* So JAVA_LEX_LIT is safe. */
1209       JAVA_LEX_LIT (literal_token, radix);
1210 #endif
1211       /* This section of code is borrowed from gcc/c-lex.c  */
1212       if (!overflow)
1213         {
1214           bytes = GET_TYPE_PRECISION (long_type_node);
1215           for (i = bytes; i < TOTAL_PARTS; i++)
1216             if (parts [i])
1217               {
1218                 overflow = 1;
1219                 break;
1220               }
1221         }
1222       high = low = 0;
1223       for (i = 0; i < HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR; i++)
1224         {
1225           high |= ((HOST_WIDE_INT) parts[i + (HOST_BITS_PER_WIDE_INT
1226                                               / HOST_BITS_PER_CHAR)]
1227                    << (i * HOST_BITS_PER_CHAR));
1228           low |= (HOST_WIDE_INT) parts[i] << (i * HOST_BITS_PER_CHAR);
1229         }
1230       /* End borrowed section.  */
1231
1232       /* Range checking */
1233       if (long_suffix)
1234         {
1235           /* 9223372036854775808L is valid if operand of a '-'. Otherwise
1236              9223372036854775807L is the biggest `long' literal that can be
1237              expressed using a 10 radix. For other radixes, everything that
1238              fits withing 64 bits is OK. */
1239           int hb = (high >> 31);
1240           if (overflow || (hb && low && radix == 10)
1241               || (hb && high & 0x7fffffff && radix == 10))
1242             JAVA_INTEGRAL_RANGE_ERROR ("Numeric overflow for `long' literal");
1243         }
1244       else
1245         {
1246           /* 2147483648 is valid if operand of a '-'. Otherwise,
1247              2147483647 is the biggest `int' literal that can be
1248              expressed using a 10 radix. For other radixes, everything
1249              that fits within 32 bits is OK.  As all literals are
1250              signed, we sign extend here. */
1251           int hb = (low >> 31) & 0x1;
1252           if (overflow || high || (hb && low & 0x7fffffff && radix == 10))
1253             JAVA_INTEGRAL_RANGE_ERROR ("Numeric overflow for `int' literal");
1254           high = -hb;
1255         }
1256 #ifndef JC1_LITE
1257       value = build_int_2 (low, high);
1258       JAVA_RADIX10_FLAG (value) = radix == 10;
1259       SET_LVAL_NODE_TYPE (value, long_suffix ? long_type_node : int_type_node);
1260 #else
1261       SET_LVAL_NODE_TYPE (build_int_2 (low, high),
1262                           long_suffix ? long_type_node : int_type_node);
1263 #endif
1264       return INT_LIT_TK;
1265     }
1266
1267   /* Character literals */
1268   if (c == '\'')
1269     {
1270       int char_lit;
1271       if ((c = java_get_unicode ()) == '\\')
1272         char_lit = java_parse_escape_sequence ();
1273       else
1274         {
1275           if (c == '\n' || c == '\'')
1276             java_lex_error ("Invalid character literal", 0);
1277           char_lit = c;
1278         }
1279
1280       c = java_get_unicode ();
1281
1282       if ((c == '\n') || (c == UEOF))
1283         java_lex_error ("Character literal not terminated at end of line", 0);
1284       if (c != '\'')
1285         java_lex_error ("Syntax error in character literal", 0);
1286
1287       if (char_lit == JAVA_CHAR_ERROR)
1288         char_lit = 0;           /* We silently convert it to zero */
1289
1290       JAVA_LEX_CHAR_LIT (char_lit);
1291       SET_LVAL_NODE_TYPE (build_int_2 (char_lit, 0), char_type_node);
1292       return CHAR_LIT_TK;
1293     }
1294
1295   /* String literals */
1296   if (c == '"')
1297     {
1298       int no_error;
1299       char *string;
1300
1301       for (no_error = 1, c = java_get_unicode (); 
1302            c != UEOF && c != '"' && c != '\n'; c = java_get_unicode ())
1303         {
1304           if (c == '\\')
1305             c = java_parse_escape_sequence ();
1306           if (c == JAVA_CHAR_ERROR)
1307             {
1308               no_error = 0;
1309               c = 0;            /* We silently convert it to zero.  */
1310             }
1311           java_unicode_2_utf8 (c);
1312         }
1313       if (c == '\n' || c == UEOF) /* ULT */
1314         {
1315           lineno--;             /* Refer to the line the terminator was seen */
1316           java_lex_error ("String not terminated at end of line", 0);
1317           lineno++;
1318         }
1319
1320       obstack_1grow (&temporary_obstack, '\0');
1321       string = obstack_finish (&temporary_obstack);
1322 #ifndef JC1_LITE
1323       if (!no_error || (c != '"'))
1324         java_lval->node = error_mark_node; /* Requires futher testing FIXME */
1325       else
1326         java_lval->node = build_string (strlen (string), string);
1327 #endif
1328       obstack_free (&temporary_obstack, string);
1329       return STRING_LIT_TK;
1330     }
1331
1332   /* Separator */
1333   switch (c)
1334     {
1335     case '(':
1336       JAVA_LEX_SEP (c);
1337       BUILD_OPERATOR (OP_TK);
1338     case ')':
1339       JAVA_LEX_SEP (c);
1340       return CP_TK;
1341     case '{':
1342       JAVA_LEX_SEP (c);
1343       if (ctxp->ccb_indent == 1)
1344         ctxp->first_ccb_indent1 = lineno;
1345       ctxp->ccb_indent++;
1346       BUILD_OPERATOR (OCB_TK);
1347     case '}':
1348       JAVA_LEX_SEP (c);
1349       ctxp->ccb_indent--;
1350       if (ctxp->ccb_indent == 1)
1351         ctxp->last_ccb_indent1 = lineno;
1352       BUILD_OPERATOR (CCB_TK);
1353     case '[':
1354       JAVA_LEX_SEP (c);
1355       BUILD_OPERATOR (OSB_TK);
1356     case ']':
1357       JAVA_LEX_SEP (c);
1358       return CSB_TK;
1359     case ';':
1360       JAVA_LEX_SEP (c);
1361       return SC_TK;
1362     case ',':
1363       JAVA_LEX_SEP (c);
1364       return C_TK;
1365     case '.':
1366       JAVA_LEX_SEP (c);
1367       BUILD_OPERATOR (DOT_TK);
1368       /*      return DOT_TK; */
1369     }
1370
1371   /* Operators */
1372   switch (c)
1373     {
1374     case '=':
1375       if ((c = java_get_unicode ()) == '=')
1376         {
1377           BUILD_OPERATOR (EQ_TK);
1378         }
1379       else
1380         {
1381           /* Equals is used in two different locations. In the 
1382              variable_declarator: rule, it has to be seen as '=' as opposed
1383              to being seen as an ordinary assignment operator in
1384              assignment_operators: rule.  */
1385           java_unget_unicode ();
1386           BUILD_OPERATOR (ASSIGN_TK);
1387         }
1388       
1389     case '>':
1390       switch ((c = java_get_unicode ()))
1391         {
1392         case '=':
1393           BUILD_OPERATOR (GTE_TK);
1394         case '>':
1395           switch ((c = java_get_unicode ()))
1396             {
1397             case '>':
1398               if ((c = java_get_unicode ()) == '=')
1399                 {
1400                   BUILD_OPERATOR2 (ZRS_ASSIGN_TK);
1401                 }
1402               else
1403                 {
1404                   java_unget_unicode ();
1405                   BUILD_OPERATOR (ZRS_TK);
1406                 }
1407             case '=':
1408               BUILD_OPERATOR2 (SRS_ASSIGN_TK);
1409             default:
1410               java_unget_unicode ();
1411               BUILD_OPERATOR (SRS_TK);
1412             }
1413         default:
1414           java_unget_unicode ();
1415           BUILD_OPERATOR (GT_TK);
1416         }
1417         
1418     case '<':
1419       switch ((c = java_get_unicode ()))
1420         {
1421         case '=':
1422           BUILD_OPERATOR (LTE_TK);
1423         case '<':
1424           if ((c = java_get_unicode ()) == '=')
1425             {
1426               BUILD_OPERATOR2 (LS_ASSIGN_TK);
1427             }
1428           else
1429             {
1430               java_unget_unicode ();
1431               BUILD_OPERATOR (LS_TK);
1432             }
1433         default:
1434           java_unget_unicode ();
1435           BUILD_OPERATOR (LT_TK);
1436         }
1437
1438     case '&':
1439       switch ((c = java_get_unicode ()))
1440         {
1441         case '&':
1442           BUILD_OPERATOR (BOOL_AND_TK);
1443         case '=':
1444           BUILD_OPERATOR2 (AND_ASSIGN_TK);
1445         default:
1446           java_unget_unicode ();
1447           BUILD_OPERATOR (AND_TK);
1448         }
1449
1450     case '|':
1451       switch ((c = java_get_unicode ()))
1452         {
1453         case '|':
1454           BUILD_OPERATOR (BOOL_OR_TK);
1455         case '=':
1456           BUILD_OPERATOR2 (OR_ASSIGN_TK);
1457         default:
1458           java_unget_unicode ();
1459           BUILD_OPERATOR (OR_TK);
1460         }
1461
1462     case '+':
1463       switch ((c = java_get_unicode ()))
1464         {
1465         case '+':
1466           BUILD_OPERATOR (INCR_TK);
1467         case '=':
1468           BUILD_OPERATOR2 (PLUS_ASSIGN_TK);
1469         default:
1470           java_unget_unicode ();
1471           BUILD_OPERATOR (PLUS_TK);
1472         }
1473
1474     case '-':
1475       switch ((c = java_get_unicode ()))
1476         {
1477         case '-':
1478           BUILD_OPERATOR (DECR_TK);
1479         case '=':
1480           BUILD_OPERATOR2 (MINUS_ASSIGN_TK);
1481         default:
1482           java_unget_unicode ();
1483           BUILD_OPERATOR (MINUS_TK);
1484         }
1485
1486     case '*':
1487       if ((c = java_get_unicode ()) == '=')
1488         {
1489           BUILD_OPERATOR2 (MULT_ASSIGN_TK);
1490         }
1491       else
1492         {
1493           java_unget_unicode ();
1494           BUILD_OPERATOR (MULT_TK);
1495         }
1496
1497     case '/':
1498       if ((c = java_get_unicode ()) == '=')
1499         {
1500           BUILD_OPERATOR2 (DIV_ASSIGN_TK);
1501         }
1502       else
1503         {
1504           java_unget_unicode ();
1505           BUILD_OPERATOR (DIV_TK);
1506         }
1507
1508     case '^':
1509       if ((c = java_get_unicode ()) == '=')
1510         {
1511           BUILD_OPERATOR2 (XOR_ASSIGN_TK);
1512         }
1513       else
1514         {
1515           java_unget_unicode ();
1516           BUILD_OPERATOR (XOR_TK);
1517         }
1518
1519     case '%':
1520       if ((c = java_get_unicode ()) == '=')
1521         {
1522           BUILD_OPERATOR2 (REM_ASSIGN_TK);
1523         }
1524       else
1525         {
1526           java_unget_unicode ();
1527           BUILD_OPERATOR (REM_TK);
1528         }
1529
1530     case '!':
1531       if ((c = java_get_unicode()) == '=')
1532         {
1533           BUILD_OPERATOR (NEQ_TK);
1534         }
1535       else
1536         {
1537           java_unget_unicode ();
1538           BUILD_OPERATOR (NEG_TK);
1539         }
1540           
1541     case '?':
1542       JAVA_LEX_OP ("?");
1543       BUILD_OPERATOR (REL_QM_TK);
1544     case ':':
1545       JAVA_LEX_OP (":");
1546       BUILD_OPERATOR (REL_CL_TK);
1547     case '~':
1548       BUILD_OPERATOR (NOT_TK);
1549     }
1550   
1551   /* Keyword, boolean literal or null literal */
1552   for (first_unicode = c, all_ascii = 1, ascii_index = 0; 
1553        JAVA_PART_CHAR_P (c); c = java_get_unicode ())
1554     {
1555       java_unicode_2_utf8 (c);
1556       if (all_ascii && c >= 128)
1557         all_ascii = 0;
1558       ascii_index++;
1559     }
1560
1561   obstack_1grow (&temporary_obstack, '\0');
1562   string = obstack_finish (&temporary_obstack);
1563   java_unget_unicode ();
1564
1565   /* If we have something all ascii, we consider a keyword, a boolean
1566      literal, a null literal or an all ASCII identifier.  Otherwise,
1567      this is an identifier (possibly not respecting formation rule).  */
1568   if (all_ascii)
1569     {
1570       const struct java_keyword *kw;
1571       if ((kw=java_keyword (string, ascii_index)))
1572         {
1573           JAVA_LEX_KW (string);
1574           switch (kw->token)
1575             {
1576             case PUBLIC_TK:       case PROTECTED_TK: case STATIC_TK:
1577             case ABSTRACT_TK:     case FINAL_TK:     case NATIVE_TK:
1578             case SYNCHRONIZED_TK: case TRANSIENT_TK: case VOLATILE_TK:
1579             case PRIVATE_TK:      case STRICT_TK:
1580               SET_MODIFIER_CTX (kw->token);
1581               return MODIFIER_TK;
1582             case FLOAT_TK:
1583               SET_LVAL_NODE (float_type_node);
1584               return FP_TK;
1585             case DOUBLE_TK:
1586               SET_LVAL_NODE (double_type_node);
1587               return FP_TK;
1588             case BOOLEAN_TK:
1589               SET_LVAL_NODE (boolean_type_node);
1590               return BOOLEAN_TK;
1591             case BYTE_TK:
1592               SET_LVAL_NODE (byte_type_node);
1593               return INTEGRAL_TK;
1594             case SHORT_TK:
1595               SET_LVAL_NODE (short_type_node);
1596               return INTEGRAL_TK;
1597             case INT_TK:
1598               SET_LVAL_NODE (int_type_node);
1599               return INTEGRAL_TK;
1600             case LONG_TK:
1601               SET_LVAL_NODE (long_type_node);
1602               return INTEGRAL_TK;
1603             case CHAR_TK:
1604               SET_LVAL_NODE (char_type_node);
1605               return INTEGRAL_TK;
1606
1607               /* Keyword based literals */
1608             case TRUE_TK:
1609             case FALSE_TK:
1610               SET_LVAL_NODE ((kw->token == TRUE_TK ? 
1611                               boolean_true_node : boolean_false_node));
1612               return BOOL_LIT_TK;
1613             case NULL_TK:
1614               SET_LVAL_NODE (null_pointer_node);
1615               return NULL_TK;
1616
1617               /* Some keyword we want to retain information on the location
1618                  they where found */
1619             case CASE_TK:
1620             case DEFAULT_TK:
1621             case SUPER_TK:
1622             case THIS_TK:
1623             case RETURN_TK:
1624             case BREAK_TK:
1625             case CONTINUE_TK:
1626             case TRY_TK:
1627             case CATCH_TK:
1628             case THROW_TK:
1629             case INSTANCEOF_TK:
1630               BUILD_OPERATOR (kw->token);
1631
1632             default:
1633               return kw->token;
1634             }
1635         }
1636     }
1637   
1638   /* We may have an ID here */
1639   if (JAVA_START_CHAR_P (first_unicode))
1640     {
1641       JAVA_LEX_ID (string);
1642       java_lval->node = BUILD_ID_WFL (GET_IDENTIFIER (string));
1643       return ID_TK;
1644     }
1645
1646   /* Everything else is an invalid character in the input */
1647   {
1648     char lex_error_buffer [128];
1649     sprintf (lex_error_buffer, "Invalid character `%s' in input", 
1650              java_sprint_unicode (ctxp->c_line, ctxp->c_line->current));
1651     java_lex_error (lex_error_buffer, 1);
1652   }
1653   return 0;
1654 }
1655
1656 #ifndef JC1_LITE
1657 /* This is called by the parser to see if an error should be generated
1658    due to numeric overflow.  This function only handles the particular
1659    case of the largest negative value, and is only called in the case
1660    where this value is not preceded by `-'.  */
1661 static void
1662 error_if_numeric_overflow (value)
1663      tree value;
1664 {
1665   if (TREE_CODE (value) == INTEGER_CST && JAVA_RADIX10_FLAG (value))
1666     {
1667       unsigned HOST_WIDE_INT lo, hi;
1668
1669       lo = TREE_INT_CST_LOW (value);
1670       hi = TREE_INT_CST_HIGH (value);
1671       if (TREE_TYPE (value) == long_type_node)
1672         {
1673           int hb = (hi >> 31);
1674           if (hb && !(hi & 0x7fffffff))
1675             java_lex_error ("Numeric overflow for `long' literal", 0);
1676         }
1677       else
1678         {
1679           int hb = (lo >> 31) & 0x1;
1680           if (hb && !(lo & 0x7fffffff))
1681             java_lex_error ("Numeric overflow for `int' literal", 0);
1682         }
1683     }
1684 }
1685 #endif /* JC1_LITE */
1686
1687 static void
1688 java_unicode_2_utf8 (unicode)
1689     unicode_t unicode;
1690 {
1691   if (RANGE (unicode, 0x01, 0x7f))
1692     obstack_1grow (&temporary_obstack, (char)unicode);
1693   else if (RANGE (unicode, 0x80, 0x7ff) || unicode == 0)
1694     {
1695       obstack_1grow (&temporary_obstack,
1696                      (unsigned char)(0xc0 | ((0x7c0 & unicode) >> 6)));
1697       obstack_1grow (&temporary_obstack,
1698                      (unsigned char)(0x80 | (unicode & 0x3f)));
1699     }
1700   else                          /* Range 0x800-0xffff */
1701     {
1702       obstack_1grow (&temporary_obstack,
1703                      (unsigned char)(0xe0 | (unicode & 0xf000) >> 12));
1704       obstack_1grow (&temporary_obstack,
1705                      (unsigned char)(0x80 | (unicode & 0x0fc0) >> 6));
1706       obstack_1grow (&temporary_obstack,
1707                      (unsigned char)(0x80 | (unicode & 0x003f)));
1708     }
1709 }
1710
1711 #ifndef JC1_LITE
1712 static tree
1713 build_wfl_node (node)
1714      tree node;
1715 {
1716   node = build_expr_wfl (node, ctxp->filename, ctxp->elc.line, ctxp->elc.col);
1717   /* Prevent java_complete_lhs from short-circuiting node (if constant). */
1718   TREE_TYPE (node) = NULL_TREE;
1719   return node;
1720 }
1721 #endif
1722
1723 static void
1724 java_lex_error (msg, forward)
1725      const char *msg ATTRIBUTE_UNUSED;
1726      int forward ATTRIBUTE_UNUSED;
1727 {
1728 #ifndef JC1_LITE
1729   ctxp->elc.line = ctxp->c_line->lineno;
1730   ctxp->elc.col = ctxp->c_line->char_col-1+forward;
1731
1732   /* Might be caught in the middle of some error report */
1733   ctxp->java_error_flag = 0;
1734   java_error (NULL);
1735   java_error (msg);
1736 #endif
1737 }
1738
1739 #ifndef JC1_LITE
1740 static int
1741 java_is_eol (fp, c)
1742   FILE *fp;
1743   int c;
1744 {
1745   int next;
1746   switch (c)
1747     {
1748     case '\r':
1749       next = getc (fp);
1750       if (next != '\n' && next != EOF)
1751         ungetc (next, fp);
1752       return 1;
1753     case '\n':
1754       return 1;
1755     default:
1756       return 0;
1757     }  
1758 }
1759 #endif
1760
1761 char *
1762 java_get_line_col (filename, line, col)
1763      const char *filename ATTRIBUTE_UNUSED;
1764      int line ATTRIBUTE_UNUSED, col ATTRIBUTE_UNUSED;
1765 {
1766 #ifdef JC1_LITE
1767   return 0;
1768 #else
1769   /* Dumb implementation. Doesn't try to cache or optimize things. */
1770   /* First line of the file is line 1, first column is 1 */
1771
1772   /* COL == -1 means, at the CR/LF in LINE */
1773   /* COL == -2 means, at the first non space char in LINE */
1774
1775   FILE *fp;
1776   int c, ccol, cline = 1;
1777   int current_line_col = 0;
1778   int first_non_space = 0;
1779   char *base;
1780
1781   if (!(fp = fopen (filename, "r")))
1782     fatal_io_error ("can't open %s", filename);
1783
1784   while (cline != line)
1785     {
1786       c = getc (fp);
1787       if (c == EOF)
1788         {
1789           static const char msg[] = "<<file too short - unexpected EOF>>";
1790           obstack_grow (&temporary_obstack, msg, sizeof(msg)-1);
1791           goto have_line;
1792         }
1793       if (java_is_eol (fp, c))
1794         cline++;
1795     }
1796
1797   /* Gather the chars of the current line in a buffer */
1798   for (;;)
1799     {
1800       c = getc (fp);
1801       if (c < 0 || java_is_eol (fp, c))
1802         break;
1803       if (!first_non_space && !JAVA_WHITE_SPACE_P (c))
1804         first_non_space = current_line_col;
1805       obstack_1grow (&temporary_obstack, c);
1806       current_line_col++;
1807     }
1808  have_line:
1809
1810   obstack_1grow (&temporary_obstack, '\n');
1811
1812   if (col == -1)
1813     {
1814       col = current_line_col;
1815       first_non_space = 0;
1816     }
1817   else if (col == -2)
1818     col = first_non_space;
1819   else
1820     first_non_space = 0;
1821
1822   /* Place the '^' a the right position */
1823   base = obstack_base (&temporary_obstack);
1824   for (ccol = 1; ccol <= col+3; ccol++)
1825     {
1826       /* Compute \t when reaching first_non_space */
1827       char c = (first_non_space ?
1828                 (base [ccol-1] == '\t' ? '\t' : ' ') : ' ');
1829       obstack_1grow (&temporary_obstack, c);
1830     }
1831   obstack_grow0 (&temporary_obstack, "^", 1);
1832
1833   fclose (fp);
1834   return obstack_finish (&temporary_obstack);
1835 #endif
1836 }
1837
1838 #ifndef JC1_LITE
1839 static int
1840 utf8_cmp (str, length, name)
1841      const unsigned char *str;
1842      int length;
1843      const char *name;
1844 {
1845   const unsigned char *limit = str + length;
1846   int i;
1847
1848   for (i = 0; name[i]; ++i)
1849     {
1850       int ch = UTF8_GET (str, limit);
1851       if (ch != name[i])
1852         return ch - name[i];
1853     }
1854
1855   return str == limit ? 0 : 1;
1856 }
1857
1858 /* A sorted list of all C++ keywords.  */
1859
1860 static const char *const cxx_keywords[] =
1861 {
1862   "_Complex",
1863   "__alignof",
1864   "__alignof__",
1865   "__asm",
1866   "__asm__",
1867   "__attribute",
1868   "__attribute__",
1869   "__builtin_va_arg",
1870   "__complex",
1871   "__complex__",
1872   "__const",
1873   "__const__",
1874   "__extension__",
1875   "__imag",
1876   "__imag__",
1877   "__inline",
1878   "__inline__",
1879   "__label__",
1880   "__null",
1881   "__real",
1882   "__real__",
1883   "__restrict",
1884   "__restrict__",
1885   "__signed",
1886   "__signed__",
1887   "__typeof",
1888   "__typeof__",
1889   "__volatile",
1890   "__volatile__",
1891   "and",
1892   "and_eq",
1893   "asm",
1894   "auto",
1895   "bitand",
1896   "bitor",
1897   "bool",
1898   "break",
1899   "case",
1900   "catch",
1901   "char",
1902   "class",
1903   "compl",
1904   "const",
1905   "const_cast",
1906   "continue",
1907   "default",
1908   "delete",
1909   "do",
1910   "double",
1911   "dynamic_cast",
1912   "else",
1913   "enum",
1914   "explicit",
1915   "export",
1916   "extern",
1917   "false",
1918   "float",
1919   "for",
1920   "friend",
1921   "goto",
1922   "if",
1923   "inline",
1924   "int",
1925   "long",
1926   "mutable",
1927   "namespace",
1928   "new",
1929   "not",
1930   "not_eq",
1931   "operator",
1932   "or",
1933   "or_eq",
1934   "private",
1935   "protected",
1936   "public",
1937   "register",
1938   "reinterpret_cast",
1939   "return",
1940   "short",
1941   "signed",
1942   "sizeof",
1943   "static",
1944   "static_cast",
1945   "struct",
1946   "switch",
1947   "template",
1948   "this",      
1949   "throw",
1950   "true",
1951   "try",
1952   "typedef",
1953   "typeid",
1954   "typename",
1955   "typeof",
1956   "union",
1957   "unsigned",
1958   "using",
1959   "virtual",
1960   "void",
1961   "volatile",
1962   "wchar_t",
1963   "while",
1964   "xor",
1965   "xor_eq"
1966 };
1967
1968 /* Return true if NAME is a C++ keyword.  */
1969
1970 int
1971 cxx_keyword_p (name, length)
1972      const char *name;
1973      int length;
1974 {
1975   int last = ARRAY_SIZE (cxx_keywords);
1976   int first = 0;
1977   int mid = (last + first) / 2;
1978   int old = -1;
1979
1980   for (mid = (last + first) / 2;
1981        mid != old;
1982        old = mid, mid = (last + first) / 2)
1983     {
1984       int kwl = strlen (cxx_keywords[mid]);
1985       int min_length = kwl > length ? length : kwl;
1986       int r = utf8_cmp (name, min_length, cxx_keywords[mid]);
1987
1988       if (r == 0)
1989         {
1990           int i;
1991           /* We've found a match if all the remaining characters are
1992              `$'.  */
1993           for (i = min_length; i < length && name[i] == '$'; ++i)
1994             ;
1995           if (i == length)
1996             return 1;
1997           r = 1;
1998         }
1999
2000       if (r < 0)
2001         last = mid;
2002       else
2003         first = mid;
2004     }
2005   return 0;
2006 }
2007 #endif /* JC1_LITE */