OSDN Git Service

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