OSDN Git Service

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