home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 2 / AACD 2.iso / AACD / Programming / jikes-1.02 / src / stream.h < prev    next >
Encoding:
C/C++ Source or Header  |  1999-08-26  |  11.7 KB  |  392 lines

  1. // $Id: stream.h,v 1.9 1999/08/26 15:34:10 shields 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 "config.h"
  14. #include <sys/stat.h>
  15. #include <limits.h>
  16. #include <iostream.h>
  17. #include <stddef.h>
  18. #include <stdio.h>
  19. #include "javadef.h"
  20. #include "javasym.h"
  21. #include "tuple.h"
  22. #include "tab.h"
  23. #include "lookup.h"
  24.  
  25. class Control;
  26. class Input_info;
  27. class Scanner;
  28. class Symbol;
  29. class FileSymbol;
  30. class ZipFile;
  31.  
  32. class StreamError
  33. {
  34. public:
  35.     enum StreamErrorKind
  36.     {
  37.         BAD_TOKEN,
  38.         BAD_OCTAL_CONSTANT,
  39.         EMPTY_CHARACTER_CONSTANT,
  40.         UNTERMINATED_CHARACTER_CONSTANT,
  41.         UNTERMINATED_COMMENT,
  42.         UNTERMINATED_STRING_CONSTANT,
  43.         INVALID_HEX_CONSTANT,
  44.         INVALID_FLOATING_CONSTANT_EXPONENT,
  45.         INVALID_UNICODE_ESCAPE
  46.     };
  47.  
  48.     unsigned start_location,
  49.              end_location;
  50.     StreamErrorKind kind;
  51.  
  52.     void Initialize(StreamErrorKind kind_, unsigned start_location_, unsigned end_location_)
  53.     {
  54.         kind = kind_;
  55.         start_location = start_location_;
  56.         end_location = end_location_;
  57.  
  58.         return;
  59.     }
  60. };
  61.  
  62.  
  63. //
  64. // LexStream holds a stream of tokens generated from an input and
  65. // provides methods to retrieve information from the stream.
  66. //
  67. class LexStream
  68. {
  69. public:
  70.     typedef int TypeIndex;
  71.     typedef int TokenIndex;
  72.     typedef int CommentIndex;
  73.     enum { INFINITY = INT_MAX }; // the largest possible value for TokenIndex
  74.  
  75.     FileSymbol *file_symbol;
  76.  
  77.     inline TokenIndex Next(TokenIndex i)
  78.          { return (++i < token_stream.Length() ? i : token_stream.Length() - 1); }
  79.  
  80.     inline TokenIndex Previous(TokenIndex i) { return (i <= 0 ? 0 : i - 1); }
  81.  
  82.     inline TokenIndex Peek() { return Next(index); }
  83.  
  84.     inline void Reset(TokenIndex i = 1) { index = Previous(i); }
  85.  
  86.     inline TokenIndex Gettoken() { return index = Next(index); }
  87.  
  88.     inline TokenIndex Gettoken(TokenIndex end_token)
  89.          { return index = (index < end_token ? Next(index) : token_stream.Length() - 1); }
  90.  
  91.     inline TokenIndex Badtoken() { return 0; }
  92.  
  93.     inline unsigned Kind(TokenIndex i) { return tokens[i].Kind(); }
  94.  
  95.     inline unsigned Location(TokenIndex i) { return tokens[i].Location(); }
  96.  
  97.     inline unsigned Line(TokenIndex i) { return FindLine(tokens[i].Location()); }
  98.  
  99.     inline unsigned Column(TokenIndex i) { return columns ? columns[i] : (input_buffer ? FindColumn(tokens[i].Location()) : 0); }
  100.  
  101.     inline bool AfterEol(TokenIndex i) { return (i < 1 ? true : Line(i - 1) < Line(i)); }
  102.  
  103.     inline bool IsDeprecated(TokenIndex i) { return tokens[i].Deprecated(); }
  104.  
  105.     inline TokenIndex MatchingBrace(TokenIndex i) { return tokens[i].additional_info.right_brace; }
  106.  
  107.     wchar_t *NameString(TokenIndex i)
  108.     {
  109.         return (NameSymbol(i) || LiteralSymbol(i) ? tokens[i].additional_info.symbol -> Name()
  110.                                                   : KeywordName(tokens[i].Kind()));
  111.     }
  112.  
  113.     int NameStringLength(TokenIndex i)
  114.     {
  115.         return (NameSymbol(i) || LiteralSymbol(i) ? tokens[i].additional_info.symbol -> NameLength()
  116.                                                   : wcslen(KeywordName(tokens[i].Kind())));
  117.     }
  118.  
  119.     class LiteralSymbol *LiteralSymbol(TokenIndex);
  120.  
  121.     class NameSymbol *NameSymbol(TokenIndex);
  122.  
  123.     char *FileName();
  124.     int FileNameLength();
  125.  
  126.     inline int LineLength(unsigned line_no) { return locations[line_no + 1] - locations[line_no]; }
  127.     inline int LineStart(unsigned line_no)  { return locations[line_no]; }
  128.     inline int LineEnd(unsigned line_no)    { return locations[line_no + 1] - 1; }
  129.  
  130.     inline int LineSegmentLength(TokenIndex i)
  131.         { return Tab::Wcslen(input_buffer, tokens[i].Location(), LineEnd(Line(i))); }
  132.  
  133.     //
  134.     // For a sequence of tokens in a given range find out how many large
  135.     // characters they contain and compute the appropriate offset.
  136.     //
  137.     inline int WcharOffset(TokenIndex start, TokenIndex end)
  138.     {
  139.         int offset = 0;
  140.         for (TokenIndex i = start; i <= end; i++)
  141.         {
  142.             for (wchar_t *str = NameString(i); *str; str++)
  143.             {
  144.                  if (*str > 0xff)
  145.                     offset += 5;
  146.             }
  147.         }
  148.  
  149.         return offset;
  150.     }
  151.  
  152.     //
  153.     // When only an end token is supplied, the start token is assume to be the first one on the same line.
  154.     //
  155.     inline int WcharOffset(TokenIndex end)
  156.     {
  157.         TokenIndex start;
  158.         unsigned the_line = Line(end);
  159.         for (start = end; Line(start) == the_line; start--)
  160.             ;
  161.         start++;
  162.  
  163.         return WcharOffset(start, end);
  164.     }
  165.  
  166.     wchar_t *InputBuffer() { return input_buffer; }
  167.     size_t InputBufferLength() { return input_buffer_length; }
  168.  
  169.     CommentIndex FirstComment(TokenIndex);
  170.  
  171.     inline int NumTypes() { return type_index.Length(); }
  172.     inline TokenIndex Type(int i) { return types[i]; }
  173.  
  174.     inline int NumTokens() { return token_stream.Length(); }
  175.  
  176.     inline int NumComments() { return comment_stream.Length(); }
  177.  
  178.     inline TokenIndex PrecedingToken(CommentIndex i) { return comments[i].previous_token; }
  179.  
  180.     inline unsigned CommentLocation(CommentIndex i)  { return comments[i].location; }
  181.  
  182.     inline wchar_t *CommentString(CommentIndex i)    { return comments[i].string; }
  183.  
  184.     inline int CommentStringLength(CommentIndex i)   { return comments[i].length; }
  185.  
  186.     inline int NumBadTokens() { return bad_tokens.Length(); }
  187.  
  188. #ifdef TEST
  189.     int file_read;
  190. #endif
  191.  
  192.     //*
  193.     //* Constructors and Destructor.
  194.     //*
  195.     LexStream(Control &control_, FileSymbol *file_symbol_) : control(control_),
  196.                                                              file_symbol(file_symbol_),
  197.                                                              initial_reading_of_input(true),
  198.                                                              input_buffer(NULL),
  199.                                                              input_buffer_length(0),
  200.                                                              comment_buffer(NULL),
  201.                                                              token_stream(12, 16),
  202.                                                              tokens(NULL),
  203.                                                              columns(NULL),
  204.                                                              comment_stream(10, 8),
  205.                                                              comments(NULL),
  206.                                                              line_location(12, 8),
  207.                                                              locations(NULL)
  208. #ifdef TEST
  209.                                                            , file_read(0)
  210. #endif
  211.     {}
  212.  
  213.     bool ComputeColumns()
  214.     {
  215.         RereadInput();
  216.         if (input_buffer)
  217.             InitializeColumns();
  218.  
  219.         DestroyInput();
  220.  
  221.         return (columns != NULL);
  222.     }
  223.  
  224.     void RereadInput();
  225.     ~LexStream();
  226.  
  227.  
  228.     void DestroyInput()
  229.     {
  230.         delete [] input_buffer;
  231.         input_buffer = NULL;
  232.  
  233.         delete [] comment_buffer;
  234.         comment_buffer = NULL;
  235.     }
  236.  
  237.     void SortMessages();
  238.     void PrintMessages();
  239.     void PrintEmacsMessage(int);
  240.     void PrintSmallSource(int);
  241.     void PrintLargeSource(int);
  242.     void PrintMessage(StreamError::StreamErrorKind);
  243.  
  244.     void SetUpComments()
  245.     {
  246.         RereadInput();
  247.         //
  248.         // Calculate the length of the string required to save the comments.
  249.         // Allocate the buffer, save the comments in the buffer and update their
  250.         // respective "string" pointer.
  251.         //
  252.         int length = 0,
  253.             i;
  254.  
  255.         for (i = 1; i < comment_stream.Length(); i++)
  256.             length += (comments[i].length + 1);
  257.         comment_buffer = new wchar_t[length];
  258.         wchar_t *ptr = comment_buffer;
  259.         for (i = 1; i < comment_stream.Length(); i++)
  260.         {
  261.             memmove(ptr, &(input_buffer[comments[i].location]), comments[i].length * sizeof(wchar_t));
  262.             comments[i].string = ptr;
  263.             ptr += comments[i].length;
  264.             *ptr++ = U_NULL;
  265.         }
  266.  
  267.         return;
  268.     }
  269.  
  270. #ifdef TEST
  271. void LexStream::Dump(); // temporary function used to dump token stream.
  272. #endif
  273.  
  274.     //
  275.     // Return the total size of space allocated for the tokens.
  276.     //
  277.     size_t TokenSpaceAllocated(void)
  278.     {
  279.         return token_stream.Length() * sizeof(Token);
  280.     }
  281.  
  282.     //
  283.     // Return the total size of space allocated for the comments.
  284.     //
  285.     size_t CommentSpaceAllocated(void)
  286.     {
  287.         return comment_stream.Length() * sizeof(Comment);
  288.     }
  289.  
  290. private:
  291.  
  292.     friend class Scanner;
  293.  
  294.     class Token
  295.     {
  296.         //
  297.         // It is expected that a location will be set for every token. Therefore,
  298.         // as we are setting the location, we also reset the deprecated bit to 0.
  299.         // If it is subsequently discovered that the token is followed by one or more
  300.         // deprecated tags then the bit is set to 1 by an invocation of the
  301.         // function SetDeprecated. Note that a better way to resetting all the bits in
  302.         // "info" is to use the function ResetInfoAndSetLocation defined below, instead
  303.         // of using SetLocation
  304.         //
  305.         inline void SetLocation(unsigned location) { assert(location <= 0x00FFFFFF); info = (info & 0x0000007F) | (location << 8); }
  306.  
  307.     public:
  308.         unsigned info;
  309.         union
  310.         {
  311.             Symbol   *symbol;
  312.             TokenIndex right_brace;
  313.         } additional_info;
  314.  
  315.         //
  316.         // To just reset the info, this function should be invoked with a location value of 0.
  317.         //
  318.         inline void ResetInfoAndSetLocation(unsigned location)
  319.         {
  320.             assert(location <= 0x00FFFFFF);
  321.             info = (location << 8);
  322.             additional_info.symbol = NULL;
  323.         }
  324.  
  325.         inline unsigned Location()                   { return (info >> 8); }
  326.         inline void SetKind(unsigned kind)           { assert(kind <= 0x0000007F); info = (info & 0xFFFFFF80) | kind; }
  327.         inline unsigned Kind()                       { return (info & 0x0000007F); }
  328.         inline void SetDeprecated()                  { info |= 0x00000080; }
  329.         inline bool Deprecated()                     { return ((info & 0x00000080) != 0); }
  330.  
  331.         inline void SetSymbol(Symbol *symbol)        { additional_info.symbol = symbol; }
  332.         inline void SetRightBrace(TokenIndex rbrace) { additional_info.right_brace = rbrace; }
  333.     };
  334.  
  335.     TokenIndex GetNextToken(unsigned location = 0)
  336.     {
  337.         TokenIndex index = token_stream.NextIndex();
  338.         token_stream[index].ResetInfoAndSetLocation(location);
  339.  
  340.         return index;
  341.     }
  342.  
  343.     class Comment
  344.     {
  345.     public:
  346.         TokenIndex previous_token;
  347.         unsigned   location;
  348.         unsigned   length;
  349.         wchar_t   *string;
  350.     };
  351.  
  352.     Tuple<StreamError> bad_tokens;
  353.  
  354.     TokenIndex index;
  355.     Token *tokens;
  356.     unsigned short *columns;
  357.     ConvertibleArray<Token> token_stream;
  358.     Comment *comments;
  359.     ConvertibleArray<Comment> comment_stream;
  360.     unsigned *locations;
  361.     ConvertibleArray<unsigned> line_location;
  362.     TokenIndex *types;
  363.     ConvertibleArray<TokenIndex> type_index;
  364.  
  365.     void InitializeColumns();
  366.     void CompressSpace();
  367.  
  368.     bool initial_reading_of_input;
  369.  
  370.     wchar_t *input_buffer;
  371.     size_t input_buffer_length;
  372.     wchar_t *comment_buffer;
  373.  
  374.     Control &control;
  375.  
  376.     void ReadInput();
  377.     void ProcessInput(char *, long);
  378.  
  379.     wchar_t *KeywordName(int);
  380.  
  381.     unsigned FindLine(unsigned location);
  382.  
  383.     unsigned FindColumn(unsigned location)
  384.     {
  385.         assert(locations);
  386.  
  387.         return Tab::Wcslen(input_buffer, locations[FindLine(location)], location);
  388.     }
  389. };
  390.  
  391. #endif
  392.