OSDN Git Service

* buffer.h: PROTO -> PARAMS.
[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 characters
28 and returns a token for everything found but comments, white spaces
29 and line terminators. When necessary, it also fills the java_lval
30 (yylval) union. It's implemented to be called by a re-entrant parser
31 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
39 #ifndef JC1_LITE
40 extern struct obstack *expression_obstack;
41 #endif
42
43 /* Function declaration  */
44 static int java_lineterminator PARAMS ((unicode_t));
45 static char *java_sprint_unicode PARAMS ((struct java_line *, int));
46 static void java_unicode_2_utf8 PARAMS ((unicode_t));
47 static void java_lex_error PARAMS ((const char *, int));
48 #ifndef JC1_LITE
49 static int java_is_eol PARAMS ((FILE *, int));
50 static tree build_wfl_node PARAMS ((tree));
51 #endif
52 static void java_store_unicode PARAMS ((struct java_line *, unicode_t, int));
53 static unicode_t java_parse_escape_sequence PARAMS ((void));
54 static int java_letter_or_digit_p PARAMS ((unicode_t));
55 static int java_parse_doc_section PARAMS ((unicode_t));
56 static void java_parse_end_comment PARAMS ((unicode_t));
57 static unicode_t java_get_unicode PARAMS ((void));
58 static unicode_t java_read_unicode PARAMS ((int, int *));
59 static void java_store_unicode PARAMS ((struct java_line *, unicode_t, int));
60 static unicode_t java_read_char PARAMS ((void));
61 static void java_allocate_new_line PARAMS ((void));
62 static void java_unget_unicode PARAMS ((void));
63 static unicode_t java_sneak_unicode PARAMS ((void));
64
65 void
66 java_init_lex ()
67 {
68 #ifndef JC1_LITE
69   int java_lang_imported = 0;
70
71   if (!java_lang_id)
72     java_lang_id = get_identifier ("java.lang");
73   if (!java_lang_cloneable)
74     java_lang_cloneable = get_identifier ("java.lang.Cloneable");
75
76   if (!java_lang_imported)
77     {
78       tree node = build_tree_list 
79         (build_expr_wfl (java_lang_id, NULL, 0, 0), NULL_TREE);
80       read_import_dir (TREE_PURPOSE (node));
81       TREE_CHAIN (node) = ctxp->import_demand_list;
82       ctxp->import_demand_list = node;
83       java_lang_imported = 1;
84     }
85
86   if (!wfl_operator)
87     wfl_operator = build_expr_wfl (NULL_TREE, ctxp->filename, 0, 0);
88   if (!label_id)
89     label_id = get_identifier ("$L");
90   if (!wfl_append) 
91     wfl_append = build_expr_wfl (get_identifier ("append"), NULL, 0, 0);
92   if (!wfl_string_buffer)
93     wfl_string_buffer = 
94       build_expr_wfl (get_identifier ("java.lang.StringBuffer"), NULL, 0, 0);
95   if (!wfl_to_string)
96     wfl_to_string = build_expr_wfl (get_identifier ("toString"), NULL, 0, 0);
97
98   ctxp->static_initialized = ctxp->non_static_initialized = 
99     ctxp->incomplete_class = NULL_TREE;
100   
101   bzero ((PTR) ctxp->modifier_ctx, 11*sizeof (ctxp->modifier_ctx[0]));
102   bzero ((PTR) current_jcf, sizeof (JCF));
103   ctxp->current_parsed_class = NULL;
104   ctxp->package = NULL_TREE;
105 #endif
106
107   ctxp->filename = input_filename;
108   ctxp->lineno = lineno = 0;
109   ctxp->p_line = NULL;
110   ctxp->c_line = NULL;
111   ctxp->unget_utf8_value = 0;
112   ctxp->minus_seen = 0;
113   ctxp->java_error_flag = 0;
114 }
115
116 static char *
117 java_sprint_unicode (line, i)
118     struct java_line *line;
119     int i;
120 {
121   static char buffer [10];
122   if (line->unicode_escape_p [i] || line->line [i] > 128)
123     sprintf (buffer, "\\u%04x", line->line [i]);
124   else
125     {
126       buffer [0] = line->line [i];
127       buffer [1] = '\0';
128     }
129   return buffer;
130 }
131
132 static unicode_t
133 java_sneak_unicode ()
134 {
135   return (ctxp->c_line->line [ctxp->c_line->current]);
136 }
137
138 static void
139 java_unget_unicode ()
140 {
141   if (!ctxp->c_line->current)
142     fatal ("can't unget unicode - java_unget_unicode");
143   ctxp->c_line->current--;
144   ctxp->c_line->char_col -= JAVA_COLUMN_DELTA (0);
145 }
146
147 static void
148 java_allocate_new_line ()
149 {
150   unicode_t ahead = (ctxp->c_line ? ctxp->c_line->ahead[0] : '\0');
151   char ahead_escape_p = (ctxp->c_line ? 
152                          ctxp->c_line->unicode_escape_ahead_p : 0);
153
154   if (ctxp->c_line && !ctxp->c_line->white_space_only)
155     {
156       if (ctxp->p_line)
157         {
158           free (ctxp->p_line->unicode_escape_p);
159           free (ctxp->p_line->line);
160           free (ctxp->p_line);
161         }
162       ctxp->p_line = ctxp->c_line;
163       ctxp->c_line = NULL;              /* Reallocated */
164     }
165
166   if (!ctxp->c_line)
167     {
168       ctxp->c_line = (struct java_line *)xmalloc (sizeof (struct java_line));
169       ctxp->c_line->max = JAVA_LINE_MAX;
170       ctxp->c_line->line = (unicode_t *)xmalloc 
171         (sizeof (unicode_t)*ctxp->c_line->max);
172       ctxp->c_line->unicode_escape_p = 
173           (char *)xmalloc (sizeof (char)*ctxp->c_line->max);
174       ctxp->c_line->white_space_only = 0;
175     }
176
177   ctxp->c_line->line [0] = ctxp->c_line->size = 0;
178   ctxp->c_line->char_col = ctxp->c_line->current = 0;
179   if (ahead)
180     {
181       ctxp->c_line->line [ctxp->c_line->size] = ahead;
182       ctxp->c_line->unicode_escape_p [ctxp->c_line->size] = ahead_escape_p;
183       ctxp->c_line->size++;
184     }
185   ctxp->c_line->ahead [0] = 0;
186   ctxp->c_line->unicode_escape_ahead_p = 0;
187   ctxp->c_line->lineno = ++lineno;
188   ctxp->c_line->white_space_only = 1;
189 }
190
191 #define BAD_UTF8_VALUE 0xFFFE
192
193 static unicode_t
194 java_read_char ()
195 {
196   int c;
197   int c1, c2;
198
199   if (ctxp->unget_utf8_value)
200     {
201       int to_return = ctxp->unget_utf8_value;
202       ctxp->unget_utf8_value = 0;
203       return (to_return);
204     }
205
206   c = GETC ();
207
208   if (c < 128)
209     return (unicode_t)c;
210   if (c == EOF)
211     return UEOF;
212   else
213     {
214       if ((c & 0xe0) == 0xc0)
215         {
216           c1 = GETC ();
217           if ((c1 & 0xc0) == 0x80)
218             return (unicode_t)(((c &0x1f) << 6) + (c1 & 0x3f));
219           c = c1;
220         }
221       else if ((c & 0xf0) == 0xe0)
222         {
223           c1 = GETC ();
224           if ((c1 & 0xc0) == 0x80)
225             {
226               c2 = GETC ();
227               if ((c2 & 0xc0) == 0x80)
228                 return (unicode_t)(((c & 0xf) << 12) + 
229                                    (( c1 & 0x3f) << 6) + (c2 & 0x3f));
230               else
231                 c = c2;
232             }
233           else
234             c = c1;
235         }
236       /* We looked for a UTF8 multi-byte sequence (since we saw an initial
237          byte with the high bit set), but found invalid bytes instead.
238          If the most recent byte was Ascii (and not EOF), we should
239          unget it, in case it was a comment terminator or other delimitor. */
240       if ((c & 0x80) == 0)
241         UNGETC (c);
242       return BAD_UTF8_VALUE;
243     }
244 }
245
246 static void
247 java_store_unicode (l, c, unicode_escape_p)
248     struct java_line *l;
249     unicode_t c;
250     int unicode_escape_p;
251 {
252   if (l->size == l->max)
253     {
254       l->max += JAVA_LINE_MAX;
255       l->line = (unicode_t *) xrealloc (l->line, sizeof (unicode_t)*l->max);
256       l->unicode_escape_p = (char *) xrealloc (l->unicode_escape_p, 
257                                                sizeof (char)*l->max);
258     }
259   l->line [l->size] = c;
260   l->unicode_escape_p [l->size++] = unicode_escape_p;
261 }
262
263 static unicode_t
264 java_read_unicode (term_context, unicode_escape_p)
265     int term_context;
266     int *unicode_escape_p;
267 {
268   unicode_t c;
269   long i, base;
270
271   c = java_read_char ();
272   *unicode_escape_p = 0;
273
274   if (c != '\\')
275     return ((term_context ? c : 
276              java_lineterminator (c) ? '\n' : (unicode_t)c));
277
278   /* Count the number of preceeding '\' */
279   for (base = ftell (finput), i = base-2; c == '\\';)
280     { 
281       fseek (finput, i--, SEEK_SET);
282       c = java_read_char ();    /* Will fail if reading utf8 stream. FIXME */
283     }
284   fseek (finput, base, SEEK_SET);
285   if ((base-i-3)%2 == 0)        /* If odd number of \ seen */
286     {
287       c = java_read_char ();
288       if (c == 'u')
289         {
290           unsigned short unicode = 0;
291           int shift = 12;
292           /* Next should be 4 hex digits, otherwise it's an error.
293              The hex value is converted into the unicode, pushed into
294              the Unicode stream.  */
295           for (shift = 12; shift >= 0; shift -= 4)
296             {
297               if ((c = java_read_char ()) == UEOF)
298                 return UEOF;
299               if (c >= '0' && c <= '9')
300                 unicode |= (unicode_t)((c-'0') << shift);
301               else if ((c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'))
302                 unicode |= (unicode_t)((10+(c | 0x20)-'a') << shift);
303               else
304                   java_lex_error 
305                     ("Non hex digit in Unicode escape sequence", 0);
306             }
307           *unicode_escape_p = 1;
308           return (term_context ? unicode :
309                   (java_lineterminator (c) ? '\n' : unicode));
310         }
311       ctxp->unget_utf8_value = c;
312     }
313   return (unicode_t)'\\';
314 }
315
316 static unicode_t
317 java_get_unicode ()
318 {
319   /* It's time to read a line when... */
320   if (!ctxp->c_line || ctxp->c_line->current == ctxp->c_line->size)
321     {
322       unicode_t c;
323       java_allocate_new_line ();
324       if (ctxp->c_line->line[0] != '\n')
325         for (;;)
326           {
327             int unicode_escape_p;
328             c = java_read_unicode (0, &unicode_escape_p);
329             java_store_unicode (ctxp->c_line, c, unicode_escape_p);
330             if (ctxp->c_line->white_space_only 
331                 && !JAVA_WHITE_SPACE_P (c) && c!='\n')
332               ctxp->c_line->white_space_only = 0;
333             if ((c == '\n') || (c == UEOF))
334               break;
335           }
336     }
337   ctxp->c_line->char_col += JAVA_COLUMN_DELTA (0);
338   JAVA_LEX_CHAR (ctxp->c_line->line [ctxp->c_line->current]);
339   return ctxp->c_line->line [ctxp->c_line->current++];
340 }
341
342 static int
343 java_lineterminator (c)
344      unicode_t c;
345 {
346   int unicode_escape_p;
347   if (c == '\n')                /* CR */
348     {
349       if ((c = java_read_unicode (1, &unicode_escape_p)) != '\r')
350         {
351           ctxp->c_line->ahead [0] = c;
352           ctxp->c_line->unicode_escape_ahead_p = unicode_escape_p;
353         }
354       return 1;
355     }
356   else if (c == '\r')           /* LF */
357     {
358       if ((c = java_read_unicode (1, &unicode_escape_p)) != '\n')
359         {
360           ctxp->c_line->ahead [0] = c;
361           ctxp->c_line->unicode_escape_ahead_p = unicode_escape_p;
362         }
363       return 1;
364     }
365   else 
366     return 0;
367 }
368
369 /* Parse the end of a C style comment.
370  * C is the first character following the '/' and '*'. */
371 static void
372 java_parse_end_comment (c)
373      unicode_t c;
374 {
375
376   for ( ;; c = java_get_unicode ())
377     {
378       switch (c)
379         {
380         case UEOF:
381           java_lex_error ("Comment not terminated at end of input", 0);
382         case '*':
383           switch (c = java_get_unicode ())
384             {
385             case UEOF:
386               java_lex_error ("Comment not terminated at end of input", 0);
387             case '/':
388               return;
389             case '*':   /* reparse only '*' */
390               java_unget_unicode ();
391             }
392         }
393     }
394 }
395
396 /* Parse the documentation section. Keywords must be at the beginning
397    of a documentation comment line (ignoring white space and any `*'
398    character). Parsed keyword(s): @DEPRECATED.  */
399
400 static int
401 java_parse_doc_section (c)
402      unicode_t c;
403 {
404   int valid_tag = 0, seen_star = 0;
405
406   while (JAVA_WHITE_SPACE_P (c) || (c == '*') || c == '\n')
407     {
408       switch (c)
409         {
410         case '*':
411           seen_star = 1;
412           break;
413         case '\n': /* ULT */
414           valid_tag = 1;
415         default:
416           seen_star = 0;
417         }
418       c = java_get_unicode();
419     }
420   
421   if (c == UEOF)
422     java_lex_error ("Comment not terminated at end of input", 0);
423   
424   if (seen_star && (c == '/'))
425     return 1;                   /* Goto step1 in caller */
426
427   /* We're parsing @deprecated */
428   if (valid_tag && (c == '@'))
429     {
430       char tag [11];
431       int  tag_index = 0;
432
433       while (tag_index < 10 && c != UEOF && c != ' ' && c != '\n')
434         {
435           c = java_get_unicode ();
436           tag [tag_index++] = c;
437         }
438       
439       if (c == UEOF)
440         java_lex_error ("Comment not terminated at end of input", 0);
441       
442       java_unget_unicode ();
443       tag [tag_index] = '\0';
444
445       if (!strcmp (tag, "deprecated"))
446         ctxp->deprecated = 1;
447     }
448   return 0;
449 }
450
451 /* This function to be used only by JAVA_ID_CHAR_P (), otherwise it
452    will return a wrong result.  */
453 static int
454 java_letter_or_digit_p (c)
455      unicode_t c;
456 {
457   return _JAVA_LETTER_OR_DIGIT_P (c);
458 }
459
460 static unicode_t
461 java_parse_escape_sequence ()
462 {
463   unicode_t char_lit;
464   unicode_t c;
465
466   switch (c = java_get_unicode ())
467     {
468     case 'b':
469       return (unicode_t)0x8;
470     case 't':
471       return (unicode_t)0x9;
472     case 'n':
473       return (unicode_t)0xa;
474     case 'f':
475       return (unicode_t)0xc;
476     case 'r':
477       return (unicode_t)0xd;
478     case '"':
479       return (unicode_t)0x22;
480     case '\'':
481       return (unicode_t)0x27;
482     case '\\':
483       return (unicode_t)0x5c;
484     case '0': case '1': case '2': case '3': case '4':
485     case '5': case '6': case '7': case '8': case '9':
486       {
487         int octal_escape[3];
488         int octal_escape_index = 0;
489         
490         for (; octal_escape_index < 3 && RANGE (c, '0', '9');
491              c = java_get_unicode ())
492           octal_escape [octal_escape_index++] = c;
493
494         java_unget_unicode ();
495
496         if ((octal_escape_index == 3) && (octal_escape [0] > '3'))
497           {
498             java_lex_error ("Literal octal escape out of range", 0);
499             return JAVA_CHAR_ERROR;
500           }
501         else
502           {
503             int i, shift;
504             for (char_lit=0, i = 0, shift = 3*(octal_escape_index-1);
505                  i < octal_escape_index; i++, shift -= 3)
506               char_lit |= (octal_escape [i] - '0') << shift;
507
508             return (char_lit);
509           }
510         break;
511       }
512     case '\n':
513       return '\n';              /* ULT, caught latter as a specific error */
514     default:
515       java_lex_error ("Illegal character in escape sequence", 0);
516       return JAVA_CHAR_ERROR;
517     }
518 }
519
520 static int yylex                PARAMS ((YYSTYPE *));
521
522 static int
523 #ifdef JC1_LITE
524 yylex (java_lval)
525 #else
526 java_lex (java_lval)
527 #endif
528      YYSTYPE *java_lval;
529 {
530   unicode_t c, first_unicode;
531   int ascii_index, all_ascii;
532   char *string;
533
534   /* Translation of the Unicode escape in the raw stream of Unicode
535      characters. Takes care of line terminator.  */
536  step1:
537   /* Skip white spaces: SP, TAB and FF or ULT */ 
538   for (c = java_get_unicode ();
539        c == '\n' || JAVA_WHITE_SPACE_P (c); c = java_get_unicode ())
540     if (c == '\n')
541       {
542         ctxp->elc.line = ctxp->c_line->lineno;
543         ctxp->elc.col  = ctxp->c_line->char_col-2;
544       }
545
546   ctxp->elc.col = (ctxp->elc.col < 0 ? 0 : ctxp->elc.col);
547
548   if (c == 0x1a)                /* CTRL-Z */
549     {
550       if ((c = java_get_unicode ()) == UEOF)
551         return 0;               /* Ok here */
552       else
553         java_unget_unicode ();  /* Caught latter at the end the function */
554     }
555   /* Handle EOF here */
556   if (c == UEOF)        /* Should probably do something here... */
557     return 0;
558
559   /* Take care of eventual comments.  */
560   if (c == '/')
561     {
562       switch (c = java_get_unicode ())
563         {
564         case '/':
565           for (;;)
566             {
567               c = java_get_unicode ();
568               if (c == UEOF)
569                 java_lex_error ("Comment not terminated at end of input", 0);
570               if (c == '\n')    /* ULT */
571                 goto step1;
572             }
573           break;
574
575         case '*':
576           if ((c = java_get_unicode ()) == '*')
577             {
578               if ((c = java_get_unicode ()) == '/')
579                 goto step1;     /* Empy documentation comment  */
580               else if (java_parse_doc_section (c))
581                 goto step1;
582             }
583
584           java_parse_end_comment (c);
585           goto step1;
586           break;
587         default:
588           java_unget_unicode ();
589           c = '/';
590           break;
591         }
592     }
593
594   ctxp->elc.line = ctxp->c_line->lineno;
595   ctxp->elc.prev_col = ctxp->elc.col;
596   ctxp->elc.col = ctxp->c_line->char_col - JAVA_COLUMN_DELTA (-1);
597   if (ctxp->elc.col < 0)
598     fatal ("ctxp->elc.col < 0 - java_lex");
599
600   /* Numeric literals */
601   if (JAVA_ASCII_DIGIT (c) || (c == '.'))
602     {
603       /* This section of code is borrowed from gcc/c-lex.c  */
604 #define TOTAL_PARTS ((HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR) * 2 + 2)
605       int parts[TOTAL_PARTS];
606       HOST_WIDE_INT high, low;
607       /* End borrowed section  */
608       char literal_token [256];
609       int  literal_index = 0, radix = 10, long_suffix = 0, overflow = 0, bytes;
610       int  i;
611 #ifndef JC1_LITE
612       int  number_beginning = ctxp->c_line->current;
613 #endif
614       
615       /* We might have a . separator instead of a FP like .[0-9]* */
616       if (c == '.')
617         {
618           unicode_t peep = java_sneak_unicode ();
619
620           if (!JAVA_ASCII_DIGIT (peep))
621             {
622               JAVA_LEX_SEP('.');
623               BUILD_OPERATOR (DOT_TK);
624             }
625         }
626
627       for (i = 0; i < TOTAL_PARTS; i++)
628         parts [i] = 0;
629
630       if (c == '0')
631         {
632           c = java_get_unicode ();
633           if (c == 'x' || c == 'X')
634             {
635               radix = 16;
636               c = java_get_unicode ();
637             }
638           else if (JAVA_ASCII_DIGIT (c))
639             radix = 8;
640           else if (c == '.')
641             {
642               /* Push the '.' back and prepare for a FP parsing... */
643               java_unget_unicode ();
644               c = '0';
645             }
646           else
647             {
648               /* We have a zero literal: 0, 0{f,F}, 0{d,D} */
649               JAVA_LEX_LIT ("0", 10);
650               switch (c)
651                 {               
652                 case 'L': case 'l':
653                   SET_LVAL_NODE (long_zero_node);
654                   return (INT_LIT_TK);
655                 case 'f': case 'F':
656                   SET_LVAL_NODE (float_zero_node);
657                   return (FP_LIT_TK);
658                 case 'd': case 'D':
659                   SET_LVAL_NODE (double_zero_node);
660                   return (FP_LIT_TK);
661                 default:
662                   java_unget_unicode ();
663                   SET_LVAL_NODE (integer_zero_node);
664                   return (INT_LIT_TK);
665                 }
666             }
667         }
668       /* Parse the first part of the literal, until we find something
669          which is not a number.  */
670       while ((radix == 10 && JAVA_ASCII_DIGIT (c)) ||
671              (radix == 16 && JAVA_ASCII_HEXDIGIT (c)) ||
672              (radix == 8  && JAVA_ASCII_OCTDIGIT (c)))
673         {
674           /* We store in a string (in case it turns out to be a FP) and in
675              PARTS if we have to process a integer literal.  */
676           int numeric = (RANGE (c, '0', '9') ? c-'0' : 10 +(c|0x20)-'a');
677           int count;
678
679           literal_token [literal_index++] = c;
680           /* This section of code if borrowed from gcc/c-lex.c  */
681           for (count = 0; count < TOTAL_PARTS; count++)
682             {
683               parts[count] *= radix;
684               if (count)
685                 {
686                   parts[count]   += (parts[count-1] >> HOST_BITS_PER_CHAR);
687                   parts[count-1] &= (1 << HOST_BITS_PER_CHAR) - 1;
688                 }
689               else
690                 parts[0] += numeric;
691             }
692           if (parts [TOTAL_PARTS-1] != 0)
693             overflow = 1;
694           /* End borrowed section.  */
695           c = java_get_unicode ();
696         }
697
698       /* If we have something from the FP char set but not a digit, parse
699          a FP literal.  */
700       if (JAVA_ASCII_FPCHAR (c) && !JAVA_ASCII_DIGIT (c))
701         {
702           int stage = 0;
703           int seen_digit = (literal_index ? 1 : 0);
704           int seen_exponent = 0;
705           int fflag = 0;        /* 1 for {f,F}, 0 for {d,D}. FP literal are
706                                    double unless specified. */
707           if (radix != 10)
708             java_lex_error ("Can't express non-decimal FP literal", 0);
709
710           for (;;)
711             {
712               if (c == '.')
713                 {
714                   if (stage < 1)
715                     {
716                       stage = 1;
717                       literal_token [literal_index++ ] = c;
718                       c = java_get_unicode ();
719                     }
720                   else
721                     java_lex_error ("Invalid character in FP literal", 0);
722                 }
723
724               if (c == 'e' || c == 'E')
725                 {
726                   if (stage < 2)
727                     {
728                       /* {E,e} must have seen at list a digit */
729                       if (!seen_digit)
730                         java_lex_error ("Invalid FP literal", 0);
731                       seen_digit = 0;
732                       seen_exponent = 1;
733                       stage = 2;
734                       literal_token [literal_index++] = c;
735                       c = java_get_unicode ();
736                     }
737                   else
738                     java_lex_error ("Invalid character in FP literal", 0);
739                 }
740               if ( c == 'f' || c == 'F' || c == 'd' || c == 'D')
741                 {
742                   fflag = ((c == 'd') || (c == 'D')) ? 0 : 1;
743                   stage = 4;    /* So we fall through */
744                 }
745
746               if ((c=='-' || c =='+') && stage == 2)
747                 {
748                   stage = 3;
749                   literal_token [literal_index++] = c;
750                   c = java_get_unicode ();
751                 }
752
753               if ((stage == 0 && JAVA_ASCII_FPCHAR (c)) ||
754                   (stage == 1 && JAVA_ASCII_FPCHAR (c) && !(c == '.')) ||
755                   (stage == 2 && (JAVA_ASCII_DIGIT (c) || JAVA_FP_PM (c))) ||
756                   (stage == 3 && JAVA_ASCII_DIGIT (c)))
757                 {
758                   if (JAVA_ASCII_DIGIT (c))
759                     seen_digit = 1;
760                   literal_token [literal_index++ ] = c;
761                   c = java_get_unicode ();
762                 }
763               else
764                 {
765                   jmp_buf handler;
766                   REAL_VALUE_TYPE value;
767 #ifndef JC1_LITE
768                   tree type = (fflag ? FLOAT_TYPE_NODE : DOUBLE_TYPE_NODE);
769 #endif
770
771                   if (stage != 4) /* Don't push back fF/dD */
772                     java_unget_unicode ();
773                   
774                   /* An exponent (if any) must have seen a digit.  */
775                   if (seen_exponent && !seen_digit)
776                     java_lex_error ("Invalid FP literal", 0);
777
778                   literal_token [literal_index] = '\0';
779                   JAVA_LEX_LIT (literal_token, radix);
780
781                   if (setjmp (handler))
782                     {
783                       JAVA_FLOAT_RANGE_ERROR ((fflag ? "float" : "double"));
784                       value = DCONST0;
785                     }
786                   else
787                     {
788                       SET_FLOAT_HANDLER (handler);
789                       SET_REAL_VALUE_ATOF 
790                         (value, REAL_VALUE_ATOF (literal_token, 
791                                                  TYPE_MODE (type)));
792
793                       if (REAL_VALUE_ISINF (value))
794                         JAVA_FLOAT_RANGE_ERROR ((fflag ? "float" : "double"));
795
796                       if (REAL_VALUE_ISNAN (value))
797                         JAVA_FLOAT_RANGE_ERROR ((fflag ? "float" : "double"));
798
799                       SET_LVAL_NODE_TYPE (build_real (type, value), type);
800                       SET_FLOAT_HANDLER (NULL_PTR);
801                       return FP_LIT_TK;
802                     }
803                 }
804             }
805         } /* JAVA_ASCCI_FPCHAR (c) */
806
807       /* Here we get back to converting the integral literal.  */
808       if (c == 'L' || c == 'l')
809         long_suffix = 1;
810       else if (radix == 16 && JAVA_ASCII_LETTER (c))
811         java_lex_error ("Digit out of range in hexadecimal literal", 0);
812       else if (radix == 8  && JAVA_ASCII_DIGIT (c))
813         java_lex_error ("Digit out of range in octal literal", 0);
814       else if (radix == 16 && !literal_index)
815         java_lex_error ("No digit specified for hexadecimal literal", 0);
816       else
817         java_unget_unicode ();
818
819 #ifdef JAVA_LEX_DEBUG
820       literal_token [literal_index] = '\0'; /* So JAVA_LEX_LIT is safe. */
821       JAVA_LEX_LIT (literal_token, radix);
822 #endif
823       /* This section of code is borrowed from gcc/c-lex.c  */
824       if (!overflow)
825         {
826           bytes = GET_TYPE_PRECISION (long_type_node);
827           for (i = bytes; i < TOTAL_PARTS; i++)
828             if (parts [i])
829               {
830                 overflow = 1;
831                 break;
832               }
833         }
834       high = low = 0;
835       for (i = 0; i < HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR; i++)
836         {
837           high |= ((HOST_WIDE_INT) parts[i + (HOST_BITS_PER_WIDE_INT
838                                               / HOST_BITS_PER_CHAR)]
839                    << (i * HOST_BITS_PER_CHAR));
840           low |= (HOST_WIDE_INT) parts[i] << (i * HOST_BITS_PER_CHAR);
841         }
842       /* End borrowed section.  */
843
844       /* Range checking */
845       if (long_suffix)
846         {
847           /* 9223372036854775808L is valid if operand of a '-'. Otherwise
848              9223372036854775807L is the biggest `long' literal that can be
849              expressed using a 10 radix. For other radixes, everything that
850              fits withing 64 bits is OK. */
851           int hb = (high >> 31);
852           if (overflow || (hb && low && radix == 10) ||  
853               (hb && high & 0x7fffffff && radix == 10) ||
854               (hb && !(high & 0x7fffffff) && !ctxp->minus_seen && radix == 10))
855             JAVA_INTEGRAL_RANGE_ERROR ("Numeric overflow for `long' literal");
856         }
857       else
858         {
859           /* 2147483648 is valid if operand of a '-'. Otherwise,
860              2147483647 is the biggest `int' literal that can be
861              expressed using a 10 radix. For other radixes, everything
862              that fits within 32 bits is OK.  As all literals are
863              signed, we sign extend here. */
864           int hb = (low >> 31) & 0x1;
865           if (overflow || high || (hb && low & 0x7fffffff && radix == 10) ||
866               (hb && !(low & 0x7fffffff) && !ctxp->minus_seen && radix == 10))
867             JAVA_INTEGRAL_RANGE_ERROR ("Numeric overflow for `int' literal");
868           high = -hb;
869         }
870       ctxp->minus_seen = 0;
871       SET_LVAL_NODE_TYPE (build_int_2 (low, high),
872                           (long_suffix ? long_type_node : int_type_node));
873       return INT_LIT_TK;
874     }
875
876   ctxp->minus_seen = 0;
877   /* Character literals */
878   if (c == '\'')
879     {
880       unicode_t char_lit;
881       if ((c = java_get_unicode ()) == '\\')
882         char_lit = java_parse_escape_sequence ();
883       else
884         char_lit = c;
885
886       c = java_get_unicode ();
887       
888       if ((c == '\n') || (c == UEOF))
889         java_lex_error ("Character literal not terminated at end of line", 0);
890       if (c != '\'')
891         java_lex_error ("Syntax error in character literal", 0);
892
893       if (c == JAVA_CHAR_ERROR)
894         char_lit = 0;           /* We silently convert it to zero */
895
896       JAVA_LEX_CHAR_LIT (char_lit);
897       SET_LVAL_NODE_TYPE (build_int_2 (char_lit, 0), char_type_node);
898       return CHAR_LIT_TK;
899     }
900
901   /* String literals */
902   if (c == '"')
903     {
904       int no_error;
905       char *string;
906
907       for (no_error = 1, c = java_get_unicode (); 
908            c != '"' && c != '\n'; c = java_get_unicode ())
909         {
910           if (c == '\\')
911             c = java_parse_escape_sequence ();
912           no_error &= (c != JAVA_CHAR_ERROR ? 1 : 0);
913           java_unicode_2_utf8 (c);
914         }
915       if (c == '\n' || c == UEOF) /* ULT */
916         {
917           lineno--;             /* Refer to the line the terminator was seen */
918           java_lex_error ("String not terminated at end of line.", 0);
919           lineno++;
920         }
921
922       obstack_1grow (&temporary_obstack, '\0');
923       string = obstack_finish (&temporary_obstack);
924 #ifndef JC1_LITE
925       if (!no_error || (c != '"'))
926         java_lval->node = error_mark_node; /* Requires futher testing FIXME */
927       else
928         {
929           tree s = make_node (STRING_CST);
930           TREE_STRING_LENGTH (s) = strlen (string);
931           TREE_STRING_POINTER (s) = 
932             obstack_alloc (expression_obstack, TREE_STRING_LENGTH (s)+1);
933           strcpy (TREE_STRING_POINTER (s), string);
934           java_lval->node = s;
935         }
936 #endif
937       return STRING_LIT_TK;
938     }
939
940   /* Separator */
941   switch (c)
942     {
943     case '(':
944       JAVA_LEX_SEP (c);
945       BUILD_OPERATOR (OP_TK);
946     case ')':
947       JAVA_LEX_SEP (c);
948       return CP_TK;
949     case '{':
950       JAVA_LEX_SEP (c);
951       if (ctxp->ccb_indent == 1)
952         ctxp->first_ccb_indent1 = lineno;
953       ctxp->ccb_indent++;
954       BUILD_OPERATOR (OCB_TK);
955     case '}':
956       JAVA_LEX_SEP (c);
957       ctxp->ccb_indent--;
958       if (ctxp->ccb_indent == 1)
959         ctxp->last_ccb_indent1 = lineno;
960       BUILD_OPERATOR (CCB_TK);
961     case '[':
962       JAVA_LEX_SEP (c);
963       BUILD_OPERATOR (OSB_TK);
964     case ']':
965       JAVA_LEX_SEP (c);
966       return CSB_TK;
967     case ';':
968       JAVA_LEX_SEP (c);
969       return SC_TK;
970     case ',':
971       JAVA_LEX_SEP (c);
972       return C_TK;
973     case '.':
974       JAVA_LEX_SEP (c);
975       BUILD_OPERATOR (DOT_TK);
976       /*      return DOT_TK; */
977     }
978
979   /* Operators */
980   switch (c)
981     {
982     case '=':
983       if ((c = java_get_unicode ()) == '=')
984         {
985           BUILD_OPERATOR (EQ_TK);
986         }
987       else
988         {
989           /* Equals is used in two different locations. In the 
990              variable_declarator: rule, it has to be seen as '=' as opposed
991              to being seen as an ordinary assignment operator in
992              assignment_operators: rule.  */
993           java_unget_unicode ();
994           BUILD_OPERATOR (ASSIGN_TK);
995         }
996       
997     case '>':
998       switch ((c = java_get_unicode ()))
999         {
1000         case '=':
1001           BUILD_OPERATOR (GTE_TK);
1002         case '>':
1003           switch ((c = java_get_unicode ()))
1004             {
1005             case '>':
1006               if ((c = java_get_unicode ()) == '=')
1007                 {
1008                   BUILD_OPERATOR2 (ZRS_ASSIGN_TK);
1009                 }
1010               else
1011                 {
1012                   java_unget_unicode ();
1013                   BUILD_OPERATOR (ZRS_TK);
1014                 }
1015             case '=':
1016               BUILD_OPERATOR2 (SRS_ASSIGN_TK);
1017             default:
1018               java_unget_unicode ();
1019               BUILD_OPERATOR (SRS_TK);
1020             }
1021         default:
1022           java_unget_unicode ();
1023           BUILD_OPERATOR (GT_TK);
1024         }
1025         
1026     case '<':
1027       switch ((c = java_get_unicode ()))
1028         {
1029         case '=':
1030           BUILD_OPERATOR (LTE_TK);
1031         case '<':
1032           if ((c = java_get_unicode ()) == '=')
1033             {
1034               BUILD_OPERATOR2 (LS_ASSIGN_TK);
1035             }
1036           else
1037             {
1038               java_unget_unicode ();
1039               BUILD_OPERATOR (LS_TK);
1040             }
1041         default:
1042           java_unget_unicode ();
1043           BUILD_OPERATOR (LT_TK);
1044         }
1045
1046     case '&':
1047       switch ((c = java_get_unicode ()))
1048         {
1049         case '&':
1050           BUILD_OPERATOR (BOOL_AND_TK);
1051         case '=':
1052           BUILD_OPERATOR2 (AND_ASSIGN_TK);
1053         default:
1054           java_unget_unicode ();
1055           BUILD_OPERATOR (AND_TK);
1056         }
1057
1058     case '|':
1059       switch ((c = java_get_unicode ()))
1060         {
1061         case '|':
1062           BUILD_OPERATOR (BOOL_OR_TK);
1063         case '=':
1064           BUILD_OPERATOR2 (OR_ASSIGN_TK);
1065         default:
1066           java_unget_unicode ();
1067           BUILD_OPERATOR (OR_TK);
1068         }
1069
1070     case '+':
1071       switch ((c = java_get_unicode ()))
1072         {
1073         case '+':
1074           BUILD_OPERATOR (INCR_TK);
1075         case '=':
1076           BUILD_OPERATOR2 (PLUS_ASSIGN_TK);
1077         default:
1078           java_unget_unicode ();
1079           BUILD_OPERATOR (PLUS_TK);
1080         }
1081
1082     case '-':
1083       switch ((c = java_get_unicode ()))
1084         {
1085         case '-':
1086           BUILD_OPERATOR (DECR_TK);
1087         case '=':
1088           BUILD_OPERATOR2 (MINUS_ASSIGN_TK);
1089         default:
1090           java_unget_unicode ();
1091           ctxp->minus_seen = 1;
1092           BUILD_OPERATOR (MINUS_TK);
1093         }
1094
1095     case '*':
1096       if ((c = java_get_unicode ()) == '=')
1097         {
1098           BUILD_OPERATOR2 (MULT_ASSIGN_TK);
1099         }
1100       else
1101         {
1102           java_unget_unicode ();
1103           BUILD_OPERATOR (MULT_TK);
1104         }
1105
1106     case '/':
1107       if ((c = java_get_unicode ()) == '=')
1108         {
1109           BUILD_OPERATOR2 (DIV_ASSIGN_TK);
1110         }
1111       else
1112         {
1113           java_unget_unicode ();
1114           BUILD_OPERATOR (DIV_TK);
1115         }
1116
1117     case '^':
1118       if ((c = java_get_unicode ()) == '=')
1119         {
1120           BUILD_OPERATOR2 (XOR_ASSIGN_TK);
1121         }
1122       else
1123         {
1124           java_unget_unicode ();
1125           BUILD_OPERATOR (XOR_TK);
1126         }
1127
1128     case '%':
1129       if ((c = java_get_unicode ()) == '=')
1130         {
1131           BUILD_OPERATOR2 (REM_ASSIGN_TK);
1132         }
1133       else
1134         {
1135           java_unget_unicode ();
1136           BUILD_OPERATOR (REM_TK);
1137         }
1138
1139     case '!':
1140       if ((c = java_get_unicode()) == '=')
1141         {
1142           BUILD_OPERATOR (NEQ_TK);
1143         }
1144       else
1145         {
1146           java_unget_unicode ();
1147           BUILD_OPERATOR (NEG_TK);
1148         }
1149           
1150     case '?':
1151       JAVA_LEX_OP ("?");
1152       BUILD_OPERATOR (REL_QM_TK);
1153     case ':':
1154       JAVA_LEX_OP (":");
1155       BUILD_OPERATOR (REL_CL_TK);
1156     case '~':
1157       BUILD_OPERATOR (NOT_TK);
1158     }
1159   
1160   /* Keyword, boolean literal or null literal */
1161   for (first_unicode = c, all_ascii = 1, ascii_index = 0; 
1162        JAVA_ID_CHAR_P (c); c = java_get_unicode ())
1163     {
1164       java_unicode_2_utf8 (c);
1165       if (all_ascii && c >= 128)
1166         all_ascii = 0;
1167       ascii_index++;
1168     }
1169
1170   obstack_1grow (&temporary_obstack, '\0');
1171   string = obstack_finish (&temporary_obstack);
1172   java_unget_unicode ();
1173
1174   /* If we have something all ascii, we consider a keyword, a boolean
1175      literal, a null literal or an all ASCII identifier.  Otherwise,
1176      this is an identifier (possibly not respecting formation rule).  */
1177   if (all_ascii)
1178     {
1179       struct java_keyword *kw;
1180       if ((kw=java_keyword (string, ascii_index)))
1181         {
1182           JAVA_LEX_KW (string);
1183           switch (kw->token)
1184             {
1185             case PUBLIC_TK:       case PROTECTED_TK: case STATIC_TK:
1186             case ABSTRACT_TK:     case FINAL_TK:     case NATIVE_TK:
1187             case SYNCHRONIZED_TK: case TRANSIENT_TK: case VOLATILE_TK:
1188             case PRIVATE_TK:
1189               SET_MODIFIER_CTX (kw->token);
1190               return MODIFIER_TK;
1191             case FLOAT_TK:
1192               SET_LVAL_NODE (float_type_node);
1193               return FP_TK;
1194             case DOUBLE_TK:
1195               SET_LVAL_NODE (double_type_node);
1196               return FP_TK;
1197             case BOOLEAN_TK:
1198               SET_LVAL_NODE (boolean_type_node);
1199               return BOOLEAN_TK;
1200             case BYTE_TK:
1201               SET_LVAL_NODE (byte_type_node);
1202               return INTEGRAL_TK;
1203             case SHORT_TK:
1204               SET_LVAL_NODE (short_type_node);
1205               return INTEGRAL_TK;
1206             case INT_TK:
1207               SET_LVAL_NODE (int_type_node);
1208               return INTEGRAL_TK;
1209             case LONG_TK:
1210               SET_LVAL_NODE (long_type_node);
1211               return INTEGRAL_TK;
1212             case CHAR_TK:
1213               SET_LVAL_NODE (char_type_node);
1214               return INTEGRAL_TK;
1215
1216               /* Keyword based literals */
1217             case TRUE_TK:
1218             case FALSE_TK:
1219               SET_LVAL_NODE ((kw->token == TRUE_TK ? 
1220                               boolean_true_node : boolean_false_node));
1221               return BOOL_LIT_TK;
1222             case NULL_TK:
1223               SET_LVAL_NODE (null_pointer_node);
1224               return NULL_TK;
1225
1226               /* Some keyword we want to retain information on the location
1227                  they where found */
1228             case CASE_TK:
1229             case DEFAULT_TK:
1230             case SUPER_TK:
1231             case THIS_TK:
1232             case RETURN_TK:
1233             case BREAK_TK:
1234             case CONTINUE_TK:
1235             case TRY_TK:
1236             case CATCH_TK:
1237             case THROW_TK:
1238             case INSTANCEOF_TK:
1239               BUILD_OPERATOR (kw->token);
1240
1241             default:
1242               return kw->token;
1243             }
1244         }
1245     }
1246   
1247   /* We may have and ID here */
1248   if (JAVA_ID_CHAR_P(first_unicode) && !JAVA_DIGIT_P (first_unicode))
1249     {
1250       JAVA_LEX_ID (string);
1251       java_lval->node = BUILD_ID_WFL (GET_IDENTIFIER (string));
1252       return ID_TK;
1253     }
1254
1255   /* Everything else is an invalid character in the input */
1256   {
1257     char lex_error_buffer [128];
1258     sprintf (lex_error_buffer, "Invalid character '%s' in input", 
1259              java_sprint_unicode (ctxp->c_line, ctxp->c_line->current));
1260     java_lex_error (lex_error_buffer, 1);
1261   }
1262   return 0;
1263 }
1264
1265 static void
1266 java_unicode_2_utf8 (unicode)
1267     unicode_t unicode;
1268 {
1269   if (RANGE (unicode, 0x01, 0x7f))
1270     obstack_1grow (&temporary_obstack, (char)unicode);
1271   else if (RANGE (unicode, 0x80, 0x7ff) || unicode == 0)
1272     {
1273       obstack_1grow (&temporary_obstack,
1274                      (unsigned char)(0xc0 | ((0x7c0 & unicode) >> 6)));
1275       obstack_1grow (&temporary_obstack,
1276                      (unsigned char)(0x80 | (unicode & 0x3f)));
1277     }
1278   else                          /* Range 0x800-0xffff */
1279     {
1280       obstack_1grow (&temporary_obstack,
1281                      (unsigned char)(0xe0 | (unicode & 0xf000) >> 12));
1282       obstack_1grow (&temporary_obstack,
1283                      (unsigned char)(0x80 | (unicode & 0x0fc0) >> 6));
1284       obstack_1grow (&temporary_obstack,
1285                      (unsigned char)(0x80 | (unicode & 0x003f)));
1286     }
1287 }
1288
1289 #ifndef JC1_LITE
1290 static tree
1291 build_wfl_node (node)
1292      tree node;
1293 {
1294   return build_expr_wfl (node, ctxp->filename, ctxp->elc.line, ctxp->elc.col);
1295 }
1296 #endif
1297
1298 static void
1299 java_lex_error (msg, forward)
1300      const char *msg ATTRIBUTE_UNUSED;
1301      int forward ATTRIBUTE_UNUSED;
1302 {
1303 #ifndef JC1_LITE
1304   ctxp->elc.line = ctxp->c_line->lineno;
1305   ctxp->elc.col = ctxp->c_line->char_col-1+forward;
1306
1307   /* Might be caught in the middle of some error report */
1308   ctxp->java_error_flag = 0;
1309   java_error (NULL);
1310   java_error (msg);
1311 #endif
1312 }
1313
1314 #ifndef JC1_LITE
1315 static int
1316 java_is_eol (fp, c)
1317   FILE *fp;
1318   int c;
1319 {
1320   int next;
1321   switch (c)
1322     {
1323     case '\r':
1324       next = getc (fp);
1325       if (next != '\n' && next != EOF)
1326         ungetc (next, fp);
1327       return 1;
1328     case '\n':
1329       return 1;
1330     default:
1331       return 0;
1332     }  
1333 }
1334 #endif
1335
1336 char *
1337 java_get_line_col (filename, line, col)
1338      char *filename ATTRIBUTE_UNUSED;
1339      int line ATTRIBUTE_UNUSED, col ATTRIBUTE_UNUSED;
1340 {
1341 #ifdef JC1_LITE
1342   return 0;
1343 #else
1344   /* Dumb implementation. Doesn't try to cache or optimize things. */
1345   /* First line of the file is line 1, first column is 1 */
1346
1347   /* COL == -1 means, at the CR/LF in LINE */
1348   /* COL == -2 means, at the first non space char in LINE */
1349
1350   FILE *fp;
1351   int c, ccol, cline = 1;
1352   int current_line_col = 0;
1353   int first_non_space = 0;
1354   char *base;
1355
1356   if (!(fp = fopen (filename, "r")))
1357     fatal ("Can't open file - java_display_line_col");
1358
1359   while (cline != line)
1360     {
1361       c = getc (fp);
1362       if (c < 0)
1363         {
1364           static char msg[] = "<<file too short - unexpected EOF>>";
1365           obstack_grow (&temporary_obstack, msg, sizeof(msg)-1);
1366           goto have_line;
1367         }
1368       if (java_is_eol (fp, c))
1369         cline++;
1370     }
1371
1372   /* Gather the chars of the current line in a buffer */
1373   for (;;)
1374     {
1375       c = getc (fp);
1376       if (c < 0 || java_is_eol (fp, c))
1377         break;
1378       if (!first_non_space && !JAVA_WHITE_SPACE_P (c))
1379         first_non_space = current_line_col;
1380       obstack_1grow (&temporary_obstack, c);
1381       current_line_col++;
1382     }
1383  have_line:
1384
1385   obstack_1grow (&temporary_obstack, '\n');
1386
1387   if (col == -1)
1388     {
1389       col = current_line_col;
1390       first_non_space = 0;
1391     }
1392   else if (col == -2)
1393     col = first_non_space;
1394   else
1395     first_non_space = 0;
1396
1397   /* Place the '^' a the right position */
1398   base = obstack_base (&temporary_obstack);
1399   for (ccol = 1; ccol <= col; ccol++)
1400     {
1401       /* Compute \t when reaching first_non_space */
1402       char c = (first_non_space ?
1403                 (base [ccol-1] == '\t' ? '\t' : ' ') : ' ');
1404       obstack_1grow (&temporary_obstack, c);
1405     }
1406   obstack_grow0 (&temporary_obstack, "^", 1);
1407
1408   fclose (fp);
1409   return obstack_finish (&temporary_obstack);
1410 #endif
1411 }