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

  1. // $Id: stream.h,v 1.27 2001/02/20 06:47:51 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. #ifndef stream_INCLUDED
  11. #define stream_INCLUDED
  12.  
  13. #include "platform.h"
  14. #include "javadef.h"
  15. #include "javasym.h"
  16. #include "tuple.h"
  17. #include "tab.h"
  18. #include "lookup.h"
  19. #include "jikesapi.h"
  20.  
  21. /*
  22. //FIXME: include stuff
  23. #include <limits.h>
  24. #include <iostream.h>
  25. #include <stddef.h>
  26. #include <stdio.h>
  27. */
  28.  
  29. #if defined(HAVE_LIB_ICU_UC)
  30. #ifdef ICU131
  31. # include <ucnv.h>
  32. #else
  33. # include <unicode/ucnv.h>
  34. #endif
  35. #elif defined(HAVE_ICONV_H)
  36. # include <iconv.h>
  37. #endif
  38.  
  39. #ifdef    HAVE_JIKES_NAMESPACE
  40. namespace Jikes {    // Open namespace Jikes block
  41. #endif
  42.  
  43. class Control    ;
  44. class Input_info ;
  45. class Scanner    ;
  46. class Symbol     ;
  47. class FileSymbol ;
  48. class ZipFile    ;
  49. class LexStream  ;
  50.  
  51. class StreamError : public JikesError
  52. {
  53.     friend class LexStream;
  54.  
  55.  public:
  56.  
  57.     StreamError();
  58.     
  59.     virtual const wchar_t *getErrorMessage();
  60.     virtual const wchar_t *getErrorReport();
  61.     
  62.     virtual JikesErrorSeverity getSeverity();
  63.     virtual const char *getFileName();
  64.     
  65.     virtual int getLeftLineNo      ();
  66.     virtual int getLeftColumnNo    ();
  67.     virtual int getRightLineNo     ();
  68.     virtual int getRightColumnNo   ();
  69.     
  70.     enum StreamErrorKind
  71.     {
  72.         BAD_TOKEN,
  73.         BAD_OCTAL_CONSTANT,
  74.         EMPTY_CHARACTER_CONSTANT,
  75.         UNTERMINATED_CHARACTER_CONSTANT,
  76.         UNTERMINATED_COMMENT,
  77.         UNTERMINATED_STRING_CONSTANT,
  78.         INVALID_HEX_CONSTANT,
  79.         INVALID_FLOATING_CONSTANT_EXPONENT,
  80.         INVALID_UNICODE_ESCAPE
  81.     };
  82.  
  83.     void Initialize(StreamErrorKind kind_, unsigned start_location_, unsigned end_location_, LexStream *);
  84.  
  85.  protected:
  86.  
  87.  private:
  88.  
  89.     unsigned        start_location ;
  90.     unsigned        end_location   ;
  91.     StreamErrorKind kind           ;
  92.     
  93.     static  bool    emacs_style_report;
  94.     LexStream      *lex_stream;
  95.  
  96.     int left_line_no    ;
  97.     int left_column_no  ;
  98.     int right_line_no   ;
  99.     int right_column_no ;
  100.  
  101.     wchar_t *regularErrorString();
  102.     wchar_t *emacsErrorString();
  103.     
  104.     void PrintLargeSource(ErrorString &s);
  105.     void PrintSmallSource(ErrorString &s);
  106.  
  107.     bool initialized;
  108.     
  109. };
  110.  
  111.  
  112. // The stream class encapsulates details related to reading
  113. // a stream of possibly encoded data from the file system.
  114.  
  115. class Stream
  116. {
  117. public:
  118.   
  119.     Stream();
  120.     ~Stream();
  121.  
  122.     void DestroyInput() {
  123.         delete [] input_buffer;
  124.         input_buffer = NULL;
  125.     }
  126.  
  127.     inline wchar_t* InputBuffer() { return input_buffer; }
  128.     inline size_t InputBufferLength() { return input_buffer_length; }
  129.  
  130.     inline wchar_t* AllocateInputBuffer( size_t size ) {
  131.         return input_buffer = new wchar_t[size + 4];
  132.     }
  133.  
  134. #if defined(HAVE_LIB_ICU_UC) || defined(HAVE_ICONV_H)
  135.     static bool IsSupportedEncoding(char* encoding);
  136.     bool SetEncoding(char* encoding);
  137. #endif
  138.  
  139. protected:
  140.  
  141.     wchar_t *input_buffer;
  142.     size_t input_buffer_length;
  143.  
  144. //private: // FIXME : Make vars private once extracted from LexStream!
  145.  
  146. #if defined(HAVE_LIB_ICU_UC) || defined(HAVE_ICONV_H)
  147.  
  148. #if defined(HAVE_LIB_ICU_UC)
  149.      UConverter * _converter;
  150. #elif defined(HAVE_ICONV_H)
  151.      iconv_t _converter;
  152. #endif
  153.  
  154.     void DestroyEncoding();
  155. #endif
  156. };
  157.  
  158.  
  159. //
  160. // LexStream holds a stream of tokens generated from an input and
  161. // provides methods to retrieve information from the stream.
  162. //
  163. class LexStream : public Stream
  164. {
  165.  
  166.     friend class StreamError;
  167.     
  168.  public:
  169.     
  170.     typedef int TypeIndex;
  171.     typedef int TokenIndex;
  172.     typedef int CommentIndex;
  173.     enum { LEX_INFINITY = INT_MAX }; // the largest possible value for TokenIndex
  174.  
  175.     FileSymbol *file_symbol;
  176.  
  177.     inline TokenIndex Next(TokenIndex i)
  178.          { return (++i < token_stream.Length() ? i : token_stream.Length() - 1); }
  179.  
  180.     inline TokenIndex Previous(TokenIndex i) { return (i <= 0 ? 0 : i - 1); }
  181.  
  182.     inline TokenIndex Peek() { return Next(index); }
  183.  
  184.     inline void Reset(TokenIndex i = 1) { index = Previous(i); }
  185.  
  186.     inline TokenIndex Gettoken() { return index = Next(index); }
  187.  
  188.     inline TokenIndex Gettoken(TokenIndex end_token)
  189.          { return index = (index < end_token ? Next(index) : token_stream.Length() - 1); }
  190.  
  191.     inline TokenIndex Badtoken() { return 0; }
  192.  
  193.     inline unsigned Kind(TokenIndex i) { return tokens[i].Kind(); }
  194.  
  195.     inline unsigned Location(TokenIndex i) { return tokens[i].Location(); }
  196.  
  197.     inline unsigned Line(TokenIndex i) { return FindLine(tokens[i].Location()); }
  198.  
  199.     inline unsigned Column(TokenIndex i) { return columns ? columns[i] : (input_buffer ? FindColumn(tokens[i].Location()) : 0); }
  200.  
  201.     inline bool AfterEol(TokenIndex i) { return (i < 1 ? true : Line(i - 1) < Line(i)); }
  202.  
  203.     inline bool IsDeprecated(TokenIndex i) { return tokens[i].Deprecated(); }
  204.  
  205.     inline TokenIndex MatchingBrace(TokenIndex i) { return tokens[i].additional_info.right_brace; }
  206.  
  207.     wchar_t *NameString(TokenIndex i)
  208.     {
  209.         return (NameSymbol(i) || LiteralSymbol(i) ? tokens[i].additional_info.symbol -> Name()
  210.                                                   : KeywordName(tokens[i].Kind()));
  211.     }
  212.  
  213.     int NameStringLength(TokenIndex i)
  214.     {
  215.         return (NameSymbol(i) || LiteralSymbol(i) ? tokens[i].additional_info.symbol -> NameLength()
  216.                                                   : wcslen(KeywordName(tokens[i].Kind())));
  217.     }
  218.  
  219.     class LiteralSymbol *LiteralSymbol(TokenIndex);
  220.  
  221.     class NameSymbol *NameSymbol(TokenIndex);
  222.  
  223.     char *FileName();
  224.     size_t FileNameLength();
  225.  
  226.     inline int LineLength(unsigned line_no) { return locations[line_no + 1] - locations[line_no]; }
  227.     inline int LineStart(unsigned line_no)  { return locations[line_no]; }
  228.     inline int LineEnd(unsigned line_no)    { return locations[line_no + 1] - 1; }
  229.  
  230.     inline int LineSegmentLength(TokenIndex i)
  231.         { return Tab::Wcslen(input_buffer, tokens[i].Location(), LineEnd(Line(i))); }
  232.  
  233.     //
  234.     // For a sequence of tokens in a given range find out how many large
  235.     // characters they contain and compute the appropriate offset.
  236.     //
  237.     inline int WcharOffset(TokenIndex start, TokenIndex end)
  238.     {
  239.         int offset = 0;
  240.         for (TokenIndex i = start; i <= end; i++)
  241.         {
  242.             for (wchar_t *str = NameString(i); *str; str++)
  243.             {
  244.                  if (*str > 0xff)
  245.                     offset += 5;
  246.             }
  247.         }
  248.  
  249.         return offset;
  250.     }
  251.  
  252.     //
  253.     // When only an end token is supplied, the start token is assume to be the first one on the same line.
  254.     //
  255.     inline int WcharOffset(TokenIndex end)
  256.     {
  257.         TokenIndex start;
  258.         unsigned the_line = Line(end);
  259.         for (start = end; Line(start) == the_line; start--)
  260.             ;
  261.         start++;
  262.  
  263.         return WcharOffset(start, end);
  264.     }
  265.  
  266.     CommentIndex FirstComment(TokenIndex);
  267.  
  268.     inline int NumTypes() { return type_index.Length(); }
  269.     inline TokenIndex Type(int i) { return types[i]; }
  270.  
  271.     inline int NumTokens() { return token_stream.Length(); }
  272.  
  273.     inline int NumComments() { return comment_stream.Length(); }
  274.  
  275.     inline TokenIndex PrecedingToken(CommentIndex i) { return comments[i].previous_token; }
  276.  
  277.     inline unsigned CommentLocation(CommentIndex i)  { return comments[i].location; }
  278.  
  279.     inline wchar_t *CommentString(CommentIndex i)    { return comments[i].string; }
  280.  
  281.     inline int CommentStringLength(CommentIndex i)   { return comments[i].length; }
  282.  
  283.     inline int NumBadTokens() { return bad_tokens.Length(); }
  284.  
  285. #ifdef JIKES_DEBUG
  286.     int file_read;
  287. #endif
  288.  
  289.     //*
  290.     //* Constructors and Destructor.
  291.     //*
  292.     LexStream(Control &control_, FileSymbol *file_symbol_);
  293.  
  294.     bool ComputeColumns()
  295.     {
  296.         RereadInput();
  297.         if (input_buffer)
  298.             InitializeColumns();
  299.  
  300.         DestroyInput();
  301.  
  302.         return (columns != NULL);
  303.     }
  304.  
  305.     void RereadInput();
  306.     ~LexStream();
  307.  
  308.  
  309.     void DestroyInput()
  310.     {
  311.         Stream::DestroyInput();
  312.  
  313.         delete [] comment_buffer;
  314.         comment_buffer = NULL;
  315.     }
  316.  
  317.     void SortMessages();
  318.     void PrintMessages();
  319.  
  320.     void SetUpComments()
  321.     {
  322.         RereadInput();
  323.         //
  324.         // Calculate the length of the string required to save the comments.
  325.         // Allocate the buffer, save the comments in the buffer and update their
  326.         // respective "string" pointer.
  327.         //
  328.         int length = 0,
  329.             i;
  330.  
  331.         for (i = 1; i < comment_stream.Length(); i++)
  332.             length += (comments[i].length + 1);
  333.         comment_buffer = new wchar_t[length];
  334.         wchar_t *ptr = comment_buffer;
  335.         for (i = 1; i < comment_stream.Length(); i++)
  336.         {
  337.             memmove(ptr, &(input_buffer[comments[i].location]), comments[i].length * sizeof(wchar_t));
  338.             comments[i].string = ptr;
  339.             ptr += comments[i].length;
  340.             *ptr++ = U_NULL;
  341.         }
  342.  
  343.         return;
  344.     }
  345.  
  346. #ifdef JIKES_DEBUG
  347. void Dump(); // temporary function used to dump token stream.
  348. #endif
  349.  
  350.     //
  351.     // Return the total size of space allocated for the tokens.
  352.     //
  353.     size_t TokenSpaceAllocated(void)
  354.     {
  355.         return token_stream.Length() * sizeof(Token);
  356.     }
  357.  
  358.     //
  359.     // Return the total size of space allocated for the comments.
  360.     //
  361.     size_t CommentSpaceAllocated(void)
  362.     {
  363.         return comment_stream.Length() * sizeof(Comment);
  364.     }
  365.  
  366. private:
  367.  
  368.     int hexvalue(wchar_t ch);
  369.     
  370. #if defined(HAVE_LIB_ICU_UC) || defined(HAVE_ICONV_H)
  371.     enum UnicodeLexerState
  372.     {
  373.         START,
  374.         RAW,
  375.         CR,
  376.         QUOTE,
  377.         UNICODE_ESCAPE,
  378.         UNICODE_ESCAPE_DIGIT_0,
  379.         UNICODE_ESCAPE_DIGIT_1,
  380.         UNICODE_ESCAPE_DIGIT_2
  381.     };
  382. #endif
  383.     
  384.     friend class Scanner;
  385.  
  386.     class Token
  387.     {
  388.         //
  389.         // It is expected that a location will be set for every token. Therefore,
  390.         // as we are setting the location, we also reset the deprecated bit to 0.
  391.         // If it is subsequently discovered that the token is followed by one or more
  392.         // deprecated tags then the bit is set to 1 by an invocation of the
  393.         // function SetDeprecated. Note that a better way to resetting all the bits in
  394.         // "info" is to use the function ResetInfoAndSetLocation defined below, instead
  395.         // of using SetLocation
  396.         //
  397.         inline void SetLocation(unsigned location) { assert(location <= 0x00FFFFFF); info = (info & 0x0000007F) | (location << 8); }
  398.  
  399.     public:
  400.         unsigned info;
  401.         union
  402.         {
  403.             Symbol   *symbol;
  404.             TokenIndex right_brace;
  405.         } additional_info;
  406.  
  407.         //
  408.         // To just reset the info, this function should be invoked with a location value of 0.
  409.         //
  410.         inline void ResetInfoAndSetLocation(unsigned location)
  411.         {
  412.             assert(location <= 0x00FFFFFF);
  413.             info = (location << 8);
  414.             additional_info.symbol = NULL;
  415.         }
  416.  
  417.         inline unsigned Location()                   { return (info >> 8); }
  418.         inline void SetKind(unsigned kind)           { assert(kind <= 0x0000007F); info = (info & 0xFFFFFF80) | kind; }
  419.         inline unsigned Kind()                       { return (info & 0x0000007F); }
  420.         inline void SetDeprecated()                  { info |= 0x00000080; }
  421.         inline bool Deprecated()                     { return ((info & 0x00000080) != 0); }
  422.  
  423.         inline void SetSymbol(Symbol *symbol)        { additional_info.symbol = symbol; }
  424.         inline void SetRightBrace(TokenIndex rbrace) { additional_info.right_brace = rbrace; }
  425.     };
  426.  
  427.     TokenIndex GetNextToken(unsigned location = 0)
  428.     {
  429.         TokenIndex index = token_stream.NextIndex();
  430.         token_stream[index].ResetInfoAndSetLocation(location);
  431.  
  432.         return index;
  433.     }
  434.  
  435.     class Comment
  436.     {
  437.     public:
  438.         TokenIndex previous_token;
  439.         unsigned   location;
  440.         unsigned   length;
  441.         wchar_t   *string;
  442.     };
  443.  
  444.     Tuple<StreamError> bad_tokens;
  445.  
  446.     TokenIndex index;
  447.     Token *tokens;
  448.     unsigned short *columns;
  449.     ConvertibleArray<Token> token_stream;
  450.     Comment *comments;
  451.     ConvertibleArray<Comment> comment_stream;
  452.     unsigned *locations;
  453.     ConvertibleArray<unsigned> line_location;
  454.     TokenIndex *types;
  455.     ConvertibleArray<TokenIndex> type_index;
  456.  
  457.     void InitializeColumns();
  458.     void CompressSpace();
  459.  
  460.     bool initial_reading_of_input;
  461.  
  462.     wchar_t *comment_buffer;
  463.  
  464.     Control &control;
  465.  
  466.     void ReadInput();
  467.     void ProcessInput(const char *, long);
  468.     void ProcessInputAscii(const char *, long);
  469. #if defined(HAVE_LIB_ICU_UC) || defined(HAVE_ICONV_H)
  470.     void ProcessInputUnicode(const char *, long);
  471. #endif  
  472.  
  473.     wchar_t *KeywordName(int);
  474.  
  475.     unsigned FindLine(unsigned location);
  476.  
  477.     unsigned FindColumn(unsigned location)
  478.     {
  479.         assert(locations);
  480.  
  481.         return Tab::Wcslen(input_buffer, locations[FindLine(location)], location);
  482.     }
  483. };
  484.  
  485. #ifdef    HAVE_JIKES_NAMESPACE
  486. }            // Close namespace Jikes block
  487. #endif
  488.  
  489. #endif
  490.  
  491.