home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 20 / AACD20.BIN / AACD / Programming / Jikes / Source / src / stream.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-03-03  |  41.7 KB  |  1,310 lines

  1. // $Id: stream.cpp,v 1.48 2001/02/20 07:47:03 mdejong Exp $
  2. //
  3. // This software is subject to the terms of the IBM Jikes Compiler
  4. // License Agreement available at the following URL:
  5. // http://www.ibm.com/research/jikes.
  6. // Copyright (C) 1996, 1998, International Business Machines Corporation
  7. // and others.  All Rights Reserved.
  8. // You must accept the terms of that agreement to use this software.
  9. //
  10.  
  11. #include "stream.h"
  12. #include "code.h"
  13. #include "zip.h"
  14. #include "symbol.h"
  15. #include "control.h"
  16. #include "semantic.h"
  17.  
  18. #ifdef HAVE_CTYPE_H
  19. #include <ctype.h>
  20. #endif
  21.  
  22. #if defined(HAVE_LIB_ICU_UC)
  23. #ifdef ICU131
  24. # include <ucnv.h>
  25. #else
  26. # include <unicode/ucnv.h>
  27. #endif
  28. #elif defined(HAVE_ICONV_H)
  29. # include <iconv.h>
  30. # include <errno.h>
  31. #endif
  32.  
  33. #ifdef    HAVE_JIKES_NAMESPACE
  34. namespace Jikes {    // Open namespace Jikes block
  35. #endif
  36.  
  37. // Class StreamError
  38.  
  39. JikesError::JikesErrorSeverity StreamError::getSeverity        () 
  40.     //All Lexical errors are ERRORs.
  41.     return JikesError::JIKES_ERROR; 
  42. }
  43.  
  44. int StreamError::getLeftLineNo      () { return left_line_no    ; }
  45. int StreamError::getLeftColumnNo    () { return left_column_no  ; }
  46. int StreamError::getRightLineNo     () { return right_line_no   ; }
  47. int StreamError::getRightColumnNo   () { return right_column_no ; }
  48.  
  49. const char *StreamError::getFileName() 
  50.     assert(lex_stream);
  51.     return lex_stream -> FileName();   
  52. }
  53.  
  54. const wchar_t *StreamError::getErrorMessage() 
  55. {
  56.     switch(kind)
  57.     {
  58.     case StreamError::BAD_TOKEN:
  59.         return L"Illegal token\n";
  60.         break;
  61.     case StreamError::BAD_OCTAL_CONSTANT:
  62.         return L"Octal constant contains invalid digit\n";
  63.         break;
  64.     case StreamError::EMPTY_CHARACTER_CONSTANT:
  65.         return L"Empty character constant\n";
  66.         break;
  67.     case StreamError::UNTERMINATED_CHARACTER_CONSTANT:
  68.         return L"Character constant not properly terminated\n";
  69.         break;
  70.     case StreamError::UNTERMINATED_COMMENT:
  71.         return L"Comment not properly terminated\n";
  72.         break;
  73.     case StreamError::UNTERMINATED_STRING_CONSTANT:
  74.         return L"String constant not properly terminated\n";
  75.         break;
  76.     case StreamError::INVALID_HEX_CONSTANT:
  77.         return L"The prefix 0x must be followed by at least one hex digit\n";
  78.         break;
  79.     case StreamError::INVALID_FLOATING_CONSTANT_EXPONENT:
  80.         return L"floating-constant exponent has no digit\n";
  81.         break;
  82.     case StreamError::INVALID_UNICODE_ESCAPE:
  83.         return L"Invalid unicode escape character\n";
  84.         break;
  85.     default:
  86.         assert(false);
  87.     }
  88.  
  89.     return L"Unknown Error\n";
  90. }
  91.  
  92. bool StreamError::emacs_style_report=false;
  93.  
  94. const wchar_t *StreamError::getErrorReport() 
  95. {
  96.     /*
  97.      * We need to use this lazy initialization,
  98.      * because we can't to it in Initialize() method. Reason
  99.      * is that Find* methods are unusalble until
  100.      * LexStream::CompressSpace is called, which
  101.      * is not happend until later after scanning is done
  102.      * and all errors are reported.
  103.      * (lord)
  104.      */
  105.     if(!initialized)
  106.     {
  107.         left_line_no    = lex_stream->FindLine   ( start_location );
  108.         left_column_no  = lex_stream->FindColumn ( start_location );
  109.         right_line_no   = lex_stream->FindLine   ( end_location   );
  110.         right_column_no = lex_stream->FindColumn ( end_location   );
  111.         initialized     = true;
  112.     }
  113.  
  114.     return emacs_style_report?emacsErrorString():regularErrorString();
  115. }
  116.  
  117. wchar_t *StreamError::emacsErrorString()
  118. {
  119.     ErrorString s;
  120.  
  121.     s << getFileName()
  122.       << ':' << left_line_no  << ':' << left_column_no
  123.       << ':' << right_line_no << ':' << right_column_no
  124.       << ": Lexical: " << getErrorMessage();
  125.     
  126.     return s.Array();    
  127. }
  128.  
  129.  
  130. wchar_t *StreamError::regularErrorString() 
  131. {
  132.     ErrorString s;
  133.  
  134.     assert(lex_stream);
  135.     if(left_line_no == right_line_no)
  136.         PrintSmallSource(s);
  137.     else 
  138.         PrintLargeSource(s);
  139.     
  140.     s << "\n*** Lexical Error: "
  141.       << getErrorMessage();
  142.         
  143.     return s.Array();
  144. }
  145.  
  146. //
  147. // This procedure is invoked to print a small message that may
  148. // only span a single line. The parameter k points to the error
  149. // message in the error structure.
  150. //
  151. void StreamError::PrintSmallSource(ErrorString &s)
  152. {
  153.     s << "\n\n";
  154.     s.width(6);
  155.     s << left_line_no;
  156.     s << ". ";
  157.     for (int i = lex_stream->LineStart(left_line_no); i <= lex_stream->LineEnd(left_line_no); i++)
  158.         s << lex_stream->InputBuffer()[i];
  159.  
  160.     s.width(left_column_no + 7);
  161.     s << "";
  162.     if (left_column_no == right_column_no)
  163.         s << '^';
  164.     else
  165.     {
  166.         int offset = 0;
  167.         for (size_t i = start_location; i <= end_location; i++)
  168.         {
  169.             if (lex_stream->InputBuffer()[i] > 0xff)
  170.                 offset += 5;
  171.         }
  172.  
  173.         s << '<';
  174.         s.width(right_column_no - left_column_no + offset);
  175.         s.fill('-');
  176.         s << ">";
  177.         s.fill(' ');
  178.     }
  179. }
  180.  
  181.  
  182. //
  183. // This procedure is invoked to print a large message that may
  184. // span more than one line. The parameter message points to the
  185. // starting line. The parameter k points to the error message in
  186. // the error structure.
  187. //
  188. void StreamError::PrintLargeSource(ErrorString &s)
  189. {
  190.     if (left_line_no == right_line_no)
  191.     {
  192.         if (left_line_no == 0)
  193.             s << "\n";
  194.         else
  195.         {
  196.             s << "\n\n";
  197.             s.width(6);
  198.             s << left_line_no << ". ";
  199.             for (int i = lex_stream -> LineStart(left_line_no); i <= lex_stream -> LineEnd(left_line_no); i++)
  200.                 s << lex_stream -> InputBuffer()[i];
  201.  
  202.             int offset = 0;
  203.             for (size_t j = start_location; j <= end_location; j++)
  204.             {
  205.                 if (lex_stream -> InputBuffer()[j] > 0xff)
  206.                     offset += 5;
  207.             }
  208.  
  209.             s.width(left_column_no + 8);
  210.             s << "<";
  211.             s.width(right_column_no - left_column_no + offset);
  212.             s.fill('-');
  213.             s << ">";
  214.             s.fill(' ');
  215.         }
  216.     }
  217.     else
  218.     {
  219.         s << "\n\n";
  220.         s.width(left_column_no + 8);
  221.         s << "<";
  222.         
  223.         int segment_size = Tab::Wcslen(lex_stream->input_buffer, start_location,
  224.                                        lex_stream->LineEnd(lex_stream->FindLine(start_location)));
  225.         s.width(segment_size - 1);
  226.         s.fill('-');
  227.         s << "\n";
  228.         s.fill(' ');
  229.  
  230.         s.width(6);
  231.         s << left_line_no << ". ";
  232.         for (int i = lex_stream -> LineStart(left_line_no); i <= lex_stream -> LineEnd(left_line_no); i++)
  233.             s << lex_stream -> InputBuffer()[i];
  234.  
  235.         if (right_line_no > left_line_no + 1)
  236.         {
  237.             s.width(left_column_no + 7);
  238.             s << " ";
  239.             s << ". . .\n";
  240.         }
  241.  
  242.         s.width(6);
  243.         s << right_line_no << ". ";
  244.  
  245.         int offset = 0;
  246.         for (int j = lex_stream -> LineStart(right_line_no); j <= lex_stream -> LineEnd(right_line_no); j++)
  247.         {
  248.             wchar_t c = lex_stream -> InputBuffer()[j];
  249.             if (c > 0xff)
  250.                 offset += 5;
  251.             s << c;
  252.         }
  253.  
  254.         s.width(8);
  255.         s << "";
  256.         s.width(right_column_no - 1 + offset);
  257.         s.fill('-');
  258.         s << ">";
  259.         s.fill(' ');
  260.     }
  261. }
  262.  
  263. void StreamError::Initialize(StreamErrorKind kind_, unsigned start_location_, unsigned end_location_, LexStream *l)
  264. {
  265.     kind           = kind_           ;
  266.     start_location = start_location_ ;
  267.     end_location   = end_location_   ;
  268.     lex_stream     = l               ;
  269. }
  270.  
  271. StreamError::StreamError():initialized(false)
  272. {
  273. }
  274.  
  275.  
  276. // Class Stream
  277.  
  278. Stream::Stream()
  279. :   input_buffer(NULL),
  280.     input_buffer_length(0)
  281. #if defined(HAVE_LIB_ICU_UC)
  282.     ,_converter(NULL)
  283. #elif defined(HAVE_ICONV_H)
  284.     ,_converter((iconv_t)-1)
  285. #endif
  286. {
  287. }
  288.  
  289. Stream::~Stream()
  290. {
  291.     DestroyInput();
  292. #if defined(HAVE_LIB_ICU_UC) || defined(HAVE_ICONV_H)
  293.     DestroyEncoding();
  294. #endif
  295. }
  296.  
  297. #if defined(HAVE_LIB_ICU_UC) || defined(HAVE_ICONV_H)
  298.  
  299. // This method will return true is the given encoding
  300. // can be supported, it is static because we need to
  301. // be able to query encodings without an instance.
  302.  
  303. bool Stream::IsSupportedEncoding(char* encoding)
  304. {
  305.     bool supported;
  306.     // Create a tmp object instead of duplicating
  307.     // the code in SetEncoding and DestroyEncoding
  308.     Stream* tmp = new Stream();
  309.     supported = tmp->SetEncoding(encoding);
  310.     delete tmp;
  311.     return supported;
  312. }
  313.  
  314. bool Stream::SetEncoding(char* encoding)
  315. {
  316.     assert(encoding);
  317.     DestroyEncoding();
  318.  
  319. #if defined(HAVE_LIB_ICU_UC)
  320.     UErrorCode err = U_ZERO_ERROR;
  321.  
  322.     _converter = ucnv_open(encoding, &err);
  323.     if (!_converter)
  324.     {
  325.         return false;
  326.     }
  327.     else {
  328.         return true;
  329.     }
  330. #elif defined(HAVE_ICONV_H)
  331.     _converter = iconv_open("utf-16", encoding);
  332.     if (_converter == (iconv_t)-1)
  333.     {
  334.         return false;
  335.     }
  336.     else
  337.     {
  338.         return true;
  339.     }
  340. #endif
  341. }
  342.  
  343. void Stream::DestroyEncoding()
  344. {
  345. #if defined(HAVE_LIB_ICU_UC)
  346.     if (_converter)
  347.     {
  348.         ucnv_close(_converter);
  349.         _converter = NULL;
  350.     }
  351. #elif defined(HAVE_ICONV_H)
  352.     if (_converter != (iconv_t)-1)
  353.     {
  354.         iconv_close(_converter);
  355.         _converter = (iconv_t)-1;
  356.     }
  357. #endif
  358. }
  359.  
  360. #endif // defined(HAVE_LIB_ICU_UC) || defined(HAVE_ICONV_H)
  361.  
  362.  
  363. // Class LexStream
  364.  
  365. LexStream::LexStream(Control &control_, FileSymbol *file_symbol_) : file_symbol(file_symbol_),
  366. #ifdef JIKES_DEBUG
  367.     file_read(0),
  368. #endif
  369.     tokens(NULL),
  370.     columns(NULL),
  371.     token_stream(12, 16),
  372.     comments(NULL),
  373.     comment_stream(10, 8),
  374.     locations(NULL),
  375.     line_location(12, 8),
  376.     initial_reading_of_input(true),
  377.     comment_buffer(NULL),
  378.     control(control_)
  379. {
  380.     StreamError::emacs_style_report=!control_.option.errors;
  381. }
  382.  
  383. wchar_t *LexStream::KeywordName(int kind)
  384. {
  385.     switch(kind)
  386.     {
  387.         case TK_abstract:     return StringConstant::US_abstract; break;
  388.         case TK_boolean:      return StringConstant::US_boolean;  break;
  389.         case TK_break:        return StringConstant::US_break;    break;
  390.         case TK_byte:         return StringConstant::US_byte;     break;
  391.         case TK_case:         return StringConstant::US_case; break;
  392.         case TK_catch:        return StringConstant::US_catch; break;
  393.         case TK_char:         return StringConstant::US_char; break;
  394.         case TK_class:        return StringConstant::US_class; break;
  395.         case TK_const:        return StringConstant::US_const; break;
  396.         case TK_continue:     return StringConstant::US_continue; break;
  397.         case TK_default:      return StringConstant::US_default; break;
  398.         case TK_do:           return StringConstant::US_do; break;
  399.         case TK_double:       return StringConstant::US_double; break;
  400.         case TK_else:         return StringConstant::US_else; break;
  401.         case TK_extends:      return StringConstant::US_extends; break;
  402.         case TK_false:        return StringConstant::US_false; break;
  403.         case TK_final:        return StringConstant::US_final; break;
  404.         case TK_finally:      return StringConstant::US_finally; break;
  405.         case TK_float:        return StringConstant::US_float; break;
  406.         case TK_for:          return StringConstant::US_for; break;
  407.         case TK_goto:         return StringConstant::US_goto; break;
  408.         case TK_if:           return StringConstant::US_if; break;
  409.         case TK_implements:   return StringConstant::US_implements; break;
  410.         case TK_import:       return StringConstant::US_import; break;
  411.         case TK_instanceof:   return StringConstant::US_instanceof; break;
  412.         case TK_int:          return StringConstant::US_int; break;
  413.         case TK_interface:    return StringConstant::US_interface; break;
  414.         case TK_long:         return StringConstant::US_long; break;
  415.         case TK_native:       return StringConstant::US_native; break;
  416.         case TK_new:          return StringConstant::US_new; break;
  417.         case TK_null:         return StringConstant::US_null; break;
  418.         case TK_package:      return StringConstant::US_package; break;
  419.         case TK_private:      return StringConstant::US_private; break;
  420.         case TK_protected:    return StringConstant::US_protected; break;
  421.         case TK_public:       return StringConstant::US_public; break;
  422.         case TK_return:       return StringConstant::US_return; break;
  423.         case TK_short:        return StringConstant::US_short; break;
  424.         case TK_static:       return StringConstant::US_static; break;
  425.         case TK_strictfp:     return StringConstant::US_strictfp; break;
  426.         case TK_super:        return StringConstant::US_super; break;
  427.         case TK_switch:       return StringConstant::US_switch; break;
  428.         case TK_synchronized: return StringConstant::US_synchronized; break;
  429.         case TK_this:         return StringConstant::US_this; break;
  430.         case TK_throw:        return StringConstant::US_throw; break;
  431.         case TK_throws:       return StringConstant::US_throws; break;
  432.         case TK_transient:    return StringConstant::US_transient; break;
  433.         case TK_true:         return StringConstant::US_true; break;
  434.         case TK_try:          return StringConstant::US_try; break;
  435.         case TK_void:         return StringConstant::US_void; break;
  436.         case TK_volatile:     return StringConstant::US_volatile; break;
  437.         case TK_while:        return StringConstant::US_while; break;
  438.  
  439.         case TK_PLUS_PLUS:                  return StringConstant::US_PLUS_PLUS; break;
  440.         case TK_MINUS_MINUS:                return StringConstant::US_MINUS_MINUS; break;
  441.         case TK_EQUAL_EQUAL:                return StringConstant::US_EQUAL_EQUAL; break;
  442.         case TK_LESS_EQUAL:                 return StringConstant::US_LESS_EQUAL; break;
  443.         case TK_GREATER_EQUAL:              return StringConstant::US_GREATER_EQUAL; break;
  444.         case TK_NOT_EQUAL:                  return StringConstant::US_NOT_EQUAL; break;
  445.         case TK_LEFT_SHIFT:                 return StringConstant::US_LEFT_SHIFT; break;
  446.         case TK_RIGHT_SHIFT:                return StringConstant::US_RIGHT_SHIFT; break;
  447.         case TK_UNSIGNED_RIGHT_SHIFT:       return StringConstant::US_UNSIGNED_RIGHT_SHIFT; break;
  448.         case TK_PLUS_EQUAL:                 return StringConstant::US_PLUS_EQUAL; break;
  449.         case TK_MINUS_EQUAL:                return StringConstant::US_MINUS_EQUAL; break;
  450.         case TK_MULTIPLY_EQUAL:             return StringConstant::US_MULTIPLY_EQUAL; break;
  451.         case TK_DIVIDE_EQUAL:               return StringConstant::US_DIVIDE_EQUAL; break;
  452.         case TK_AND_EQUAL:                  return StringConstant::US_AND_EQUAL; break;
  453.         case TK_OR_EQUAL:                   return StringConstant::US_OR_EQUAL; break;
  454.         case TK_XOR_EQUAL:                  return StringConstant::US_XOR_EQUAL; break;
  455.         case TK_REMAINDER_EQUAL:            return StringConstant::US_REMAINDER_EQUAL; break;
  456.         case TK_LEFT_SHIFT_EQUAL:           return StringConstant::US_LEFT_SHIFT_EQUAL; break;
  457.         case TK_RIGHT_SHIFT_EQUAL:          return StringConstant::US_RIGHT_SHIFT_EQUAL; break;
  458.         case TK_UNSIGNED_RIGHT_SHIFT_EQUAL: return StringConstant::US_UNSIGNED_RIGHT_SHIFT_EQUAL; break;
  459.         case TK_OR_OR:                      return StringConstant::US_OR_OR; break;
  460.         case TK_AND_AND:                    return StringConstant::US_AND_AND; break;
  461.  
  462.         case TK_PLUS:                       return StringConstant::US_PLUS; break;
  463.         case TK_MINUS:                      return StringConstant::US_MINUS; break;
  464.         case TK_NOT:                        return StringConstant::US_NOT; break;
  465.         case TK_REMAINDER:                  return StringConstant::US_REMAINDER; break;
  466.         case TK_XOR:                        return StringConstant::US_XOR; break;
  467.         case TK_AND:                        return StringConstant::US_AND; break;
  468.         case TK_MULTIPLY:                   return StringConstant::US_MULTIPLY; break;
  469.         case TK_OR:                         return StringConstant::US_OR; break;
  470.         case TK_TWIDDLE:                    return StringConstant::US_TWIDDLE; break;
  471.         case TK_DIVIDE:                     return StringConstant::US_DIVIDE; break;
  472.         case TK_GREATER:                    return StringConstant::US_GREATER; break;
  473.         case TK_LESS:                       return StringConstant::US_LESS; break;
  474.         case TK_LPAREN:                     return StringConstant::US_LPAREN; break;
  475.         case TK_RPAREN:                     return StringConstant::US_RPAREN; break;
  476.         case TK_LBRACE:                     return StringConstant::US_LBRACE; break;
  477.         case TK_RBRACE:                     return StringConstant::US_RBRACE; break;
  478.         case TK_LBRACKET:                   return StringConstant::US_LBRACKET; break;
  479.         case TK_RBRACKET:                   return StringConstant::US_RBRACKET; break;
  480.         case TK_SEMICOLON:                  return StringConstant::US_SEMICOLON; break;
  481.         case TK_QUESTION:                   return StringConstant::US_QUESTION; break;
  482.         case TK_COLON:                      return StringConstant::US_COLON; break;
  483.         case TK_COMMA:                      return StringConstant::US_COMMA; break;
  484.         case TK_DOT:                        return StringConstant::US_DOT; break;
  485.         case TK_EQUAL:                      return StringConstant::US_EQUAL; break;
  486.         case TK_EOF:                        return StringConstant::US_EOF; break;
  487.         default:                            break;
  488.     }
  489.  
  490.     return StringConstant::US_EMPTY;
  491. }
  492.  
  493.  
  494. LexStream::~LexStream()
  495. {
  496. #ifdef JIKES_DEBUG
  497.     control.line_count += (file_read * (line_location.Length() - 3));
  498. #endif
  499.  
  500.     DestroyInput();
  501.  
  502.     delete [] columns;
  503.     columns = NULL;
  504. }
  505.  
  506.  
  507. //
  508. //
  509. //
  510. class LiteralSymbol *LexStream::LiteralSymbol(TokenIndex i)
  511. {
  512.     Symbol *symbol = tokens[i].additional_info.symbol;
  513.     return (symbol && (Kind(i) != TK_LBRACE) ?
  514.         symbol -> LiteralCast() :
  515.             (class LiteralSymbol *) NULL);
  516. }
  517.  
  518.  
  519. //
  520. //
  521. //
  522. class NameSymbol *LexStream::NameSymbol(TokenIndex i)
  523. {
  524.     Symbol *symbol = tokens[i].additional_info.symbol;
  525.     return (symbol && (Kind(i) != TK_LBRACE) ?
  526.         symbol -> NameCast() :
  527.             (class NameSymbol *) NULL);
  528. }
  529.  
  530.  
  531. //
  532. // Name of input file where the token appeared.
  533. //
  534. char *LexStream::FileName() { return file_symbol -> FileName(); }
  535. size_t LexStream::FileNameLength() { return file_symbol -> FileNameLength(); }
  536.  
  537.  
  538. void LexStream::InitializeColumns()
  539. {
  540.     if (! columns)
  541.     {
  542.         columns = new unsigned short[token_stream.Length()];
  543.  
  544.         int start = 0,
  545.             k = 1;
  546.  
  547.         for (size_t i = 0; i < input_buffer_length; i++)
  548.         {
  549.             if (Code::IsNewline(input_buffer[i]))
  550.                 start = i;
  551.             else
  552.             {
  553.                 if (input_buffer[i] == U_HORIZONTAL_TAB)
  554.                 {
  555.                     int offset = (i - start) - 1;
  556.                     start -= ((Tab::TabSize() - 1) - offset % Tab::TabSize());
  557.                 }
  558.                 else if (tokens[k].Location() == i)
  559.                 {
  560.                     int col = i - start;
  561.                     columns[k++] = (col < USHRT_MAX ? col : 0);
  562.                 }
  563.             }
  564.         }
  565.     }
  566.  
  567.     return;
  568. }
  569.  
  570.  
  571. //
  572. //
  573. //
  574. void LexStream::CompressSpace()
  575. {
  576.     tokens    = token_stream   .Array();
  577.     comments  = comment_stream .Array();
  578.     locations = line_location  .Array();
  579.     types     = type_index     .Array();
  580.     
  581.     if(control.option.dump_errors)
  582.         InitializeColumns();
  583.     
  584.     return;
  585. }
  586.  
  587.  
  588. //
  589. // Find and return the index of the first comment that immediately
  590. // follows tok. Return 0 if there is not a comment that immediately
  591. // follows tok.
  592. //
  593. LexStream::CommentIndex LexStream::FirstComment(TokenIndex tok)
  594. {
  595.     unsigned location = Location(tok);
  596.     int lo = 0,
  597.         hi = comment_stream.Length() - 1,
  598.         i = 0;
  599.  
  600.     if (lo < hi)
  601.     {
  602.         do
  603.         {
  604.             int mid = (lo + hi) / 2;
  605.  
  606.             if (comment_stream[mid].location < location)
  607.                  lo = mid + 1;
  608.             else hi = mid - 1;
  609.         } while (lo < hi);
  610.  
  611.         //
  612.         // at this stage lo == hi
  613.         //
  614.         i = (comment_stream[lo].location > location ? lo : lo + 1);
  615.     }
  616.  
  617.     return (i < comment_stream.Length() && comment_stream[i].previous_token == tok ? i : 0);
  618. }
  619.  
  620.  
  621. unsigned LexStream::FindLine(unsigned location)
  622. {
  623.     int lo = 0,
  624.         hi = line_location.Length() - 1;
  625.  
  626.     assert(locations);
  627.  
  628.     //
  629.     // we can place the exit test at the bottom of the loop
  630.     // since the line_location array will always contain at least
  631.     // one element.
  632.     //
  633.     do
  634.     {
  635.         int mid = (lo + hi) / 2;
  636.  
  637.         if (locations[mid] == location)
  638.             return mid;
  639.         if (locations[mid] < location)
  640.              lo = mid + 1;
  641.         else hi = mid - 1;
  642.     } while (lo < hi);
  643.  
  644.     return (locations[lo] > location ? lo - 1 : lo);
  645. }
  646.  
  647.  
  648. void LexStream::ReadInput()
  649. {
  650.     if (file_symbol -> buffer)
  651.     {
  652.         ProcessInput(file_symbol -> buffer, strlen(file_symbol -> buffer));
  653.     }
  654.     else if (file_symbol -> IsZip()) {
  655.         ZipFile *zipfile = new ZipFile(file_symbol);
  656.  
  657.         if (zipfile -> Buffer() == NULL)
  658.         {
  659.             fprintf(stderr, "chaos: Don\'t know how to process compressed (\".java\") source in a zip file\n");
  660.             assert(false);
  661.         }
  662.         else if (! file_symbol -> lex_stream) // Once the zip file is loaded, it never changes. So, we only read it the first time
  663.         {
  664.             file_symbol -> lex_stream = this;
  665.             ProcessInput(zipfile -> Buffer(), file_symbol -> uncompressed_size);
  666.         }
  667.         delete zipfile;
  668.     }
  669.     else
  670.     {
  671.         struct stat status;
  672.         JikesAPI::getInstance()->stat(FileName(), &status);
  673.  
  674.         file_symbol -> mtime = status.st_mtime; // actual time stamp of file read
  675.         file_symbol -> lex_stream = this;
  676.  
  677.  
  678.         JikesAPI::FileReader  *file = JikesAPI::getInstance()->read(FileName());
  679.         if (file)
  680.         {
  681.             ProcessInput(file->getBuffer(),file->getBufferSize());
  682.             delete file;
  683.         }
  684.     }
  685.  
  686.     initial_reading_of_input = false;
  687.  
  688.     return;
  689. }
  690.  
  691. void LexStream::RereadInput()
  692. {
  693.     if (input_buffer) // if input already available, do nothing
  694.         ;
  695. #ifdef JIKES_DEBUG
  696.     else if (file_symbol -> buffer)
  697.     {
  698.       fprintf(stderr, "chaos: Don\'t know how to RereadInput a buffer\n");
  699.       assert(false);
  700.     }
  701. #endif
  702.     else if (file_symbol -> IsZip())
  703.     {
  704.         ZipFile *zipfile = new ZipFile(file_symbol);
  705.  
  706.         if (zipfile -> Buffer() == NULL)
  707.         {
  708.             fprintf(stderr, "chaos: Don\'t know how to process compressed (\".java\") source in a zip file\n");
  709.             assert(false);
  710.         }
  711.         else ProcessInput(zipfile -> Buffer(), file_symbol -> uncompressed_size);
  712.         delete zipfile;
  713.     }
  714.     else
  715.     {
  716.         struct stat status;
  717.         JikesAPI::getInstance()->stat(FileName(), &status);
  718.  
  719.         if (status.st_mtime == file_symbol -> mtime)
  720.         {
  721.            JikesAPI::FileReader  *file = JikesAPI::getInstance()->read(FileName());
  722.            if (file)
  723.            {
  724.                ProcessInput(file->getBuffer(),file->getBufferSize());
  725.                delete file;
  726.            }
  727.         }
  728.         else
  729.         {
  730.             // TODO: File has changed !!!
  731.         }
  732.     }
  733.  
  734.     return;
  735. }
  736.  
  737.  
  738. int LexStream::hexvalue(wchar_t ch)
  739. {
  740.     switch(ch)
  741.     {
  742.     case U_a: case U_A:
  743.         return 10;
  744.     case U_b: case U_B:
  745.         return 11;
  746.     case U_c: case U_C:
  747.         return 12;
  748.     case U_d: case U_D:
  749.         return 13;
  750.     case U_e: case U_E:
  751.         return 14;
  752.     case U_f: case U_F:
  753.         return 15;
  754.     default:
  755.         return ch - U_0;
  756.     }
  757. }
  758.  
  759. //
  760. // Read filesize  characters from srcfile, convert them to unicode, and
  761. // store them in input_buffer.
  762. //
  763. void LexStream::ProcessInput(const char *buffer, long filesize)
  764. {
  765. #if defined(HAVE_LIB_ICU_UC) || defined(HAVE_ICONV_H)
  766.     LexStream::ProcessInputUnicode(buffer,filesize);
  767. #else
  768.     LexStream::ProcessInputAscii(buffer, filesize);
  769. #endif
  770. }
  771.  
  772. //
  773. // Read file_size Ascii characters from srcfile, convert them to unicode and
  774. // store them in input_buffer.
  775. //
  776. void LexStream::ProcessInputAscii(const char *buffer, long filesize)
  777. {
  778. #ifdef JIKES_DEBUG
  779.     file_read++;
  780. #endif
  781.  
  782.     wchar_t *input_ptr = AllocateInputBuffer( filesize );
  783.     *input_ptr = U_LINE_FEED; // add an initial '\n';
  784.  
  785.     if (buffer)
  786.     {
  787.         const char *source_ptr = buffer,
  788.              *source_tail = &(buffer[filesize - 1]); // point to last character read from the file.
  789.  
  790.         while(source_ptr <= source_tail)
  791.         {
  792.             *(++input_ptr) = (*source_ptr++) & 0x00ff; // The (& 0x00ff) guarantees that quantity is copied as unsigned value
  793.  
  794.             if (*input_ptr == U_CARRIAGE_RETURN)
  795.             {
  796.                 *input_ptr = U_LINE_FEED;
  797.                 if (*source_ptr == U_LINE_FEED)
  798.                     source_ptr++;
  799.             }
  800.             else if (*input_ptr == U_BACKSLASH)
  801.             {
  802.                 if (*source_ptr == U_BACKSLASH)
  803.                     *(++input_ptr) = *source_ptr++;
  804.                 else if (*source_ptr == U_u)
  805.                 {
  806.                     const char *u_ptr = source_ptr;
  807.  
  808.                     for (source_ptr++; source_ptr <= source_tail && *source_ptr == U_u; source_ptr++)
  809.                         ;
  810.                     *input_ptr = 0;
  811.                     int i;
  812.                     for (i = 0; source_ptr <= source_tail && isxdigit(*source_ptr) && i < 4; i++)
  813.                     {
  814.                         int multiplier[4] = {4096, 256, 16, 1};
  815.  
  816.                         const char ch = *source_ptr++;
  817.                         switch(ch)
  818.                         {
  819.                             case U_a: case U_A:
  820.                                 *input_ptr += (10 * multiplier[i]);
  821.                                 break;
  822.                             case U_b: case U_B:
  823.                                 *input_ptr += (11 * multiplier[i]);
  824.                                 break;
  825.                             case U_c: case U_C:
  826.                                 *input_ptr += (12 * multiplier[i]);
  827.                                 break;
  828.                             case U_d: case U_D:
  829.                                 *input_ptr += (13 * multiplier[i]);
  830.                                 break;
  831.                             case U_e: case U_E:
  832.                                 *input_ptr += (14 * multiplier[i]);
  833.                                 break;
  834.                             case U_f: case U_F:
  835.                                 *input_ptr += (15 * multiplier[i]);
  836.                                 break;
  837.                             default:
  838.                                 *input_ptr += ((ch - U_0) * multiplier[i]);
  839.                         }
  840.                     }
  841.  
  842.                     if (i != 4)
  843.                     {
  844.                         if (initial_reading_of_input)
  845.                             bad_tokens.Next().Initialize(StreamError::INVALID_UNICODE_ESCAPE,
  846.                                                          (unsigned) (input_ptr - input_buffer),
  847.                                                          (unsigned) (input_ptr - input_buffer) + (source_ptr - u_ptr), this);
  848.  
  849.                         source_ptr = u_ptr;
  850.                         *input_ptr = U_BACKSLASH;
  851.                     }
  852.                     else if (*input_ptr == U_CARRIAGE_RETURN)
  853.                     {
  854.                         *input_ptr = U_LINE_FEED;
  855.                         if (*source_ptr == U_LINE_FEED)
  856.                             source_ptr++;
  857.                         else if (*source_ptr == U_BACKSLASH)
  858.                         {
  859.                             int i;
  860.                             for (i = 1; (source_ptr + i) <= source_tail && source_ptr[i] == U_u; i++)
  861.                                 ;
  862.                             if (i > 1 && (source_ptr + i + 3) <= source_tail
  863.                                       && source_ptr[i]     == U_0
  864.                                       && source_ptr[i + 1] == U_0
  865.                                       && source_ptr[i + 2] == U_0
  866.                                       && source_ptr[i + 3] == U_a) // the escape sequence of \n is \u000a
  867.                                 source_ptr += (i + 4);
  868.                         }
  869.                     }
  870.                 }
  871.             }
  872.         }
  873.  
  874.         //
  875.         // Remove all trailing spaces
  876.         //
  877.         while((input_ptr > input_buffer) && Code::IsSpace(*input_ptr))
  878.             input_ptr--;
  879.     }
  880.  
  881.     //
  882.     // If the very last character is not CTL_Z then add CTL_Z
  883.     //
  884.     if (*input_ptr != U_CTL_Z)
  885.     {
  886.         if (*input_ptr != U_LINE_FEED)
  887.             *(++input_ptr) = U_LINE_FEED; // if the last character is not end-of-line, add end-of-line
  888.         *(++input_ptr) = U_CTL_Z;         // Mark end-of-file
  889.     }
  890.     *(++input_ptr) = U_NULL;              // add gate
  891.  
  892.     input_buffer_length = input_ptr - input_buffer;
  893.  
  894.     return;
  895. }
  896.  
  897. #if defined(HAVE_LIB_ICU_UC) || defined(HAVE_ICONV_H)
  898. //
  899. // Read file_size Ascii characters from srcfile, convert them to unicode, and
  900. // store them in input_buffer.
  901. //
  902. void LexStream::ProcessInputUnicode(const char *buffer, long filesize)
  903. {
  904.     //fprintf(stderr,"LexStream::ProcessInputUnicode called.\n");
  905. #ifdef JIKES_DEBUG
  906.     file_read++;
  907. #endif
  908.  
  909.     wchar_t *input_ptr = AllocateInputBuffer( filesize );
  910.     wchar_t *input_tail = input_ptr + filesize;
  911.     *input_ptr = U_LINE_FEED; // add an initial '\n';
  912.  
  913.     if(buffer)
  914.     {
  915.         int      escape_value;
  916.         wchar_t *escape_ptr;
  917.  
  918.         const char *source_ptr  = buffer;
  919.         const char *source_tail = buffer + filesize - 1; // point to last character read from the file.
  920.  
  921.         UnicodeLexerState saved_state = START;
  922.         UnicodeLexerState state = START;
  923. #ifdef HAVE_LIB_ICU_UC
  924.         UErrorCode err = U_ZERO_ERROR;
  925. #endif
  926.         bool oncemore = false;
  927.  
  928.         if(control.option.encoding)
  929.         {
  930.             // The encoding should have been validated by now
  931.             assert( SetEncoding(control.option.encoding) );
  932.         }
  933.  
  934.         while((source_ptr <= source_tail) || oncemore)
  935.         {
  936.             // On each iteration we advance input_ptr maximun 2 postions.
  937.             // Here we check if we are close to the end of input_buffer
  938.             if(input_ptr>=input_tail)
  939.             {
  940.                 // If this happen, reallocate it with some more space.
  941.                 // This is very rare case, which could happen if
  942.                 // one code page character is represened by several 
  943.                 // unicode characters. One of exaples of such
  944.                 // situation is unicode "surrogates".
  945.                 //
  946.                 // If such reallocation will be required, it will indeed
  947.                 // slow down compilation a bit.
  948.                 size_t cursize = input_ptr-input_buffer;
  949.                 size_t newsize = cursize+cursize/10+4; // add 10%
  950.                 wchar_t *tmp   = new wchar_t[newsize]; 
  951.                 memcpy (tmp, input_buffer, cursize*sizeof(wchar_t));
  952.                 delete [] input_buffer;
  953.                 input_buffer = tmp;
  954.                 input_tail = input_buffer + newsize - 1;
  955.                 input_ptr  = input_buffer + cursize;
  956.             }
  957.             
  958.             wchar_t ch;
  959.             
  960.             if(!oncemore)
  961.             {
  962.                 if(control.option.encoding)
  963.                 {
  964.                     const char *before = source_ptr;
  965.  
  966. #ifdef HAVE_LIB_ICU_UC
  967.                     ch=ucnv_getNextUChar (_converter,
  968.                                           &source_ptr,
  969.                                           source_tail+1,
  970.                                           &err);
  971.  
  972.                    
  973.                     if(U_FAILURE(err))
  974.                     {
  975.                         fprintf(stderr,"Conversion error: %s at byte %d\n", 
  976. #ifdef ICU131
  977.                 errorName(err),
  978. #else
  979.                                 u_errorName(err),
  980. #endif
  981.                                 int(before-buffer)
  982.                         );
  983.                         break;
  984.                     }
  985. #else
  986. #   ifdef HAVE_ICONV_H
  987.                     u1 chd[2], uni_high, uni_low;
  988.                     u1 *chp  = chd;
  989.                     // Point to 2 bytes with 16 bit type
  990.                     wchar_t* wchp = (wchar_t *) chp;
  991.                     size_t   chl  = 2;
  992.                     size_t   srcl = 1;
  993.                     size_t n = iconv(_converter,
  994. #ifdef HAVE_ERROR_CALL_ICONV_CONST
  995.                                      (char **)
  996. #endif
  997.                                      &source_ptr, &srcl,
  998.                                      (char **)&chp, &chl
  999.                     );
  1000.  
  1001.                     if(n == (size_t) -1)
  1002.                     {
  1003.                         fprintf(stderr,"Charset conversion error at offset %d: ", int(before-buffer));
  1004.                         perror("");
  1005.                         break;
  1006.                     }
  1007.  
  1008.                     // FIXME: This seems like a hack, someone should reread the docs
  1009.                     // and clean this nasty code up -> http://www.netppl.fi/~pp/glibc21/libc_6.html#SEC91
  1010.  
  1011.                     // Operate on chd buffer in endian independent fashion
  1012.                     uni_high = (u1) (*wchp);
  1013.                     uni_low = (u1) ((*wchp) >> 8);
  1014.                     ch = uni_low + (uni_high * 256);
  1015. #   endif
  1016. #endif
  1017.                     if(before==source_ptr)
  1018.                     {
  1019.                         //End of conversion
  1020.                         break;
  1021.                     }
  1022.                 }
  1023.                 else
  1024.                 {
  1025.                     ch=*source_ptr++;
  1026.                 }
  1027.             } else oncemore = false;
  1028.       
  1029.             switch(state)
  1030.             {
  1031.  
  1032.             case QUOTE:
  1033.                 if(ch==U_BACKSLASH)
  1034.                 {
  1035.                     *(++input_ptr) = U_BACKSLASH;
  1036.                     *(++input_ptr) = U_BACKSLASH;
  1037.                     state          = RAW;
  1038.                 } else if(ch==U_u)
  1039.                 {
  1040.                     escape_ptr = input_ptr;
  1041.                     state      = UNICODE_ESCAPE;
  1042.                 } else
  1043.                 {
  1044.                     *(++input_ptr )= U_BACKSLASH;
  1045.                     state          = RAW;
  1046.                     oncemore       = true;
  1047.                 }
  1048.                 break;
  1049.  
  1050.             case UNICODE_ESCAPE:
  1051.                 if(isxdigit(ch))
  1052.                 {
  1053.                     state=UNICODE_ESCAPE_DIGIT_0;
  1054.                     escape_value=hexvalue(ch)*16*16*16;
  1055.                 } else if(ch!=U_u)
  1056.                 {
  1057.                     if(initial_reading_of_input)
  1058.                         bad_tokens.Next().Initialize(StreamError::INVALID_UNICODE_ESCAPE,
  1059.                                                      (unsigned) (escape_ptr - input_buffer),
  1060.                                                      (unsigned) (input_ptr - input_buffer), this);
  1061.                 }
  1062.                 break;
  1063.  
  1064.             case UNICODE_ESCAPE_DIGIT_0:
  1065.                 if(isxdigit(ch))
  1066.                 {
  1067.                     state=UNICODE_ESCAPE_DIGIT_1;
  1068.                     escape_value+=hexvalue(ch)*16*16;
  1069.                 } else  
  1070.                 {
  1071.                     if(initial_reading_of_input)
  1072.                         bad_tokens.Next().Initialize(StreamError::INVALID_UNICODE_ESCAPE,
  1073.                                                      (unsigned) (escape_ptr - input_buffer),
  1074.                                                      (unsigned) (input_ptr - input_buffer), this);
  1075.                 }
  1076.                 break;
  1077.  
  1078.             case UNICODE_ESCAPE_DIGIT_1:
  1079.                 if(isxdigit(ch))
  1080.                 {
  1081.                     state=UNICODE_ESCAPE_DIGIT_2;
  1082.                     escape_value+=hexvalue(ch)*16;
  1083.                 } else  
  1084.                 {
  1085.                     if(initial_reading_of_input)
  1086.                         bad_tokens.Next().Initialize(StreamError::INVALID_UNICODE_ESCAPE,
  1087.                                                      (unsigned) (escape_ptr - input_buffer),
  1088.                                                      (unsigned) (input_ptr - input_buffer), this);
  1089.                 }
  1090.                 break;
  1091.  
  1092.             case UNICODE_ESCAPE_DIGIT_2:
  1093.                 if(isxdigit(ch))
  1094.                 {
  1095.                     ch       = escape_value+hexvalue(ch);
  1096.                     state    = saved_state;
  1097.                     saved_state = UNICODE_ESCAPE_DIGIT_2;
  1098.                     oncemore = true;
  1099.                 } else  
  1100.                 {
  1101.                     if(initial_reading_of_input)
  1102.                         bad_tokens.Next().Initialize(StreamError::INVALID_UNICODE_ESCAPE,
  1103.                                                      (unsigned) (escape_ptr - input_buffer),
  1104.                                                      (unsigned) (input_ptr - input_buffer), this);
  1105.                 }
  1106.                 break;
  1107.  
  1108.             case CR:
  1109.                 if (ch == U_LINE_FEED)
  1110.                 {
  1111.                     // skip line feed if it comes right after a CR.
  1112.                     state = RAW;
  1113.                 } else if (ch == U_CARRIAGE_RETURN)
  1114.                 {
  1115.                     // but if CR follows CR then the second CR is a
  1116.                     // line feed too (and note that state=CR still, afterwards,
  1117.                     // so that CR-CR-LF will be handled correctly). [CSA]
  1118.                     *(++input_ptr) = U_LINE_FEED;
  1119.                 } else if (ch == U_BACKSLASH && saved_state != UNICODE_ESCAPE_DIGIT_2)
  1120.                 {
  1121.                     saved_state = CR;
  1122.                     state       = QUOTE;
  1123.                 } else
  1124.                 {
  1125.                     state = RAW;
  1126.                     *(++input_ptr)=ch;                    
  1127.                 }
  1128.                // clear saved_state == UNICODE_ESCAPE_DIGIT_2 status
  1129.                saved_state = CR;
  1130.                 break;
  1131.  
  1132.             case START:
  1133.                 // if for some reason converter produced or passed
  1134.                 // byte order mark, it have to be ignored.
  1135.                 state = RAW;
  1136.                 if(ch==U_BOM || ch==U_REVERSE_BOM)
  1137.                     break; //ignore
  1138.                     
  1139.             case RAW:
  1140.                 if(ch==U_BACKSLASH && saved_state != UNICODE_ESCAPE_DIGIT_2)
  1141.                 {
  1142.                     state       = QUOTE;
  1143.                 } else if(ch == U_CARRIAGE_RETURN)
  1144.                 {
  1145.                     state = CR;
  1146.                     *(++input_ptr) = U_LINE_FEED;
  1147.                 } else
  1148.                 {
  1149.                     *(++input_ptr)=ch;                    
  1150.                 }
  1151.                 saved_state = RAW;
  1152.                 break;
  1153.             }
  1154.         }
  1155.     }
  1156.  
  1157.     //
  1158.     // If the very last character is not CTL_Z then add CTL_Z
  1159.     //
  1160.     if (*input_ptr != U_CTL_Z)
  1161.     {
  1162.         if (*input_ptr != U_LINE_FEED)
  1163.             *(++input_ptr) = U_LINE_FEED; // if the last character is not end-of-line, add end-of-line
  1164.         *(++input_ptr) = U_CTL_Z;         // Mark end-of-file
  1165.     }
  1166.     *(++input_ptr) = U_NULL;              // add gate
  1167.     
  1168.     input_buffer_length = input_ptr - input_buffer;
  1169.  
  1170.     return;
  1171. }
  1172. #endif // defined(HAVE_LIB_ICU_UC) || defined(HAVE_ICONV_H)
  1173.  
  1174. //
  1175. // This procedure uses a  quick sort algorithm to sort the stream ERRORS
  1176. // by their locations.
  1177. //
  1178. void LexStream::SortMessages()
  1179. {
  1180.      int lower,
  1181.          upper,
  1182.          lostack[32],
  1183.          histack[32];
  1184.  
  1185.      int top,
  1186.          i,
  1187.          j;
  1188.      StreamError pivot,
  1189.                  temp;
  1190.  
  1191.      top = 0;
  1192.      lostack[top] = 0;
  1193.      histack[top] = bad_tokens.Length() - 1;
  1194.  
  1195.      while(top >= 0)
  1196.      {
  1197.          lower = lostack[top];
  1198.          upper = histack[top];
  1199.          top--;
  1200.  
  1201.          while(upper > lower)
  1202.          {
  1203.              //
  1204.              // The array is most-likely almost sorted. Therefore,
  1205.              // we use the middle element as the pivot element.
  1206.              //
  1207.              i = (lower + upper) / 2;
  1208.              pivot = bad_tokens[i];
  1209.              bad_tokens[i] = bad_tokens[lower];
  1210.  
  1211.              //
  1212.              // Split the array section indicated by LOWER and UPPER
  1213.              // using ARRAY(LOWER) as the pivot.
  1214.              //
  1215.              i = lower;
  1216.              for (j = lower + 1; j <= upper; j++)
  1217.              {
  1218.                  if (bad_tokens[j].start_location < pivot.start_location)
  1219.                  {
  1220.                      temp = bad_tokens[++i];
  1221.                      bad_tokens[i] = bad_tokens[j];
  1222.                      bad_tokens[j] = temp;
  1223.                  }
  1224.              }
  1225.              bad_tokens[lower] = bad_tokens[i];
  1226.              bad_tokens[i] = pivot;
  1227.  
  1228.              top++;
  1229.              if ((i - lower) < (upper - i))
  1230.              {
  1231.                  lostack[top] = i + 1;
  1232.                  histack[top] = upper;
  1233.                  upper = i - 1;
  1234.              }
  1235.              else
  1236.              {
  1237.                  histack[top] = i - 1;
  1238.                  lostack[top] = lower;
  1239.                  lower = i + 1;
  1240.              }
  1241.          }
  1242.      }
  1243.  
  1244.      return;
  1245. }
  1246.  
  1247.  
  1248. //
  1249. //
  1250. //
  1251. void LexStream::PrintMessages()
  1252. {
  1253.     //
  1254.     // If control.option.dump_errors then the error messages have already been printed
  1255.     //
  1256.     if (! control.option.dump_errors)
  1257.     {
  1258.         RereadInput();
  1259.  
  1260.         if (control.option.errors)
  1261.         {
  1262.             char *file_name = FileName();
  1263.  
  1264.             Coutput << "\nFound " << NumBadTokens() << " lexical error" << (NumBadTokens() == 1 ? "" : "s")
  1265.                     << " in \""
  1266.                     << file_name
  1267.                     << "\":";
  1268.  
  1269.             if (! input_buffer)
  1270.             {
  1271.                 int length = FileNameLength();
  1272.                 wchar_t *name = new wchar_t[length + 1];
  1273.                 for (int i = 0; i < length; i++)
  1274.                     name[i] = file_name[i];
  1275.                 name[length] = U_NULL;
  1276.                 control.system_semantic -> ReportSemError(SemanticError::CANNOT_REOPEN_FILE,
  1277.                                                           0,
  1278.                                                           0,
  1279.                                                           name);
  1280.                 delete [] name;
  1281.             }
  1282.             else
  1283.             {
  1284.                 for (int i = 0; i < bad_tokens.Length(); i++)
  1285.                 {
  1286.                     JikesAPI::getInstance()->reportError(&bad_tokens[i]);
  1287.                 }
  1288.             }
  1289.         }
  1290.         else
  1291.         {
  1292.             for (int i = 0; i < bad_tokens.Length(); i++)
  1293.                 JikesAPI::getInstance()->reportError(&bad_tokens[i]);
  1294.         }
  1295.  
  1296.         DestroyInput();
  1297.  
  1298.         Coutput.flush();
  1299.     }
  1300.  
  1301.     return;
  1302. }
  1303.  
  1304. #ifdef    HAVE_JIKES_NAMESPACE
  1305. }            // Close namespace Jikes block
  1306. #endif
  1307.  
  1308.