Update procedures
[shapes.git] / source / sourcelocation.h
blobd9e5462b2355dc3bfc13f5b8279fce5d895dd0cb
1 /* This file is part of Shapes.
3 * Shapes is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * any later version.
8 * Shapes is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with Shapes. If not, see <http://www.gnu.org/licenses/>.
16 * Copyright 2008, 2009, 2014 Henrik Tidefelt
19 #pragma once
21 #include <stddef.h>
22 #include <iostream>
23 #include <vector>
24 #include <list>
25 #include <sys/types.h>
26 #include <sys/stat.h>
28 #include "Shapes_Ast_decls.h"
30 namespace Shapes
32 namespace Ast
34 class FileInfo
36 public:
37 std::string name_;
38 std::vector< Ast::Node * > topLevelNodes_;
40 FileInfo( const std::string & name );
43 class FileID
45 static const char * INPUTLIST_PREFIX;
46 static const size_t INPUTLIST_PREFIX_LENGTH;
48 public:
49 typedef enum { NORMAL_FILE, IN_MEMORY, SPECIAL, INTERNAL } Kind;
50 private:
51 Kind kind_;
52 dev_t st_dev_;
53 ino_t st_ino_; /* Also used to index an IN_MEMORY */
54 const char * strData_; /* A complete filename for a NORMAL_FILE, the identifier of a SPECIAL file, and unused for IN_MEMORY data. */
55 FileID( Kind kind, dev_t st_dev, ino_t st_ino, const char * strData );
56 public:
57 static const FileID * build_stat( const struct stat & stat, const std::string & filename );
58 static const FileID * build_inMemory( ino_t index, const std::string & sourceName );
59 static const FileID * build_fresh_inMemory( );
60 static const FileID * build_special( const char * specialName );
61 static const FileID * build_internal( const char * locationName ); /* Does not deep-copy locationName. Returns a new object each time, no matter if locationName has been used before! */
62 static bool is_inMemory( const std::string & filename, const FileID ** fileDst );
64 std::vector< Ast::Node * > & nodes( ) const;
65 const char * name( ) const;
66 bool hasPosition( ) const;
67 std::istream * open( std::ifstream * ifsMem, std::istringstream * issMem ) const;
68 void setMem( const char * data ); /* Applicable only to IN_MEMORY objects. */
69 int inMemoryIndex( ) const;
70 bool operator < ( const FileID & other ) const;
71 size_t byteColumnToUTF8Column( size_t line, size_t byteCol ) const;
72 size_t UTF8ColumnTobyteColumn( size_t line, size_t utf8Col ) const;
74 static size_t inputlistPrefixLength( );
75 static size_t UTF8ColumnTobyteColumn( const std::string & line, size_t utf8Col );
76 static size_t byteColumnToUTF8Column( const std::string & line, size_t byteCol );
78 private:
79 void initInfo( const std::string & name ) const;
82 class FileIDPtrLess
84 public:
85 bool operator () ( const FileID * fid1, const FileID * fid2 ) const
87 return (*fid1) < (*fid2);
91 /* Important note on the storage of SourceLocation instances:
92 * The basic rule is that all SourceLocation instances should remain in memory
93 * until the end of program execution. This allows any classes with shorter life
94 * cycles to use references instead of copies. However, to avoid the risk of
95 * creating references to instances that won't live forever, it is crucial that
96 * the actual instances are *exactly* the onces that will last till the end.
97 * In other words, classes whose instances won't last till the end *must* use
98 * references instead of keeping their own copes.
100 class SourceLocation
102 public:
103 static const FileID * UNKNOWN_FILE;
105 const FileID * file_;
106 size_t firstLine;
107 size_t firstColumn; /* In bytes, shall be converted to utf-8 position when displaying. */
108 size_t lastLine;
109 size_t lastColumn; /* In bytes, shall be converted to utf-8 position when displaying. */
111 /* The lifetime of a SourceLocation instance should pretty much last for the entire program execution,
112 * so that instead of making copies all the time, we can use members of type const SourceLocation &.
113 * To avoid accidentally initializing our const SourceLocation & members with instances that won't last the
114 * entire program execution, we remove access to the copy constructor.
116 * At the end of parsing, SourceLocation instances should only exist in three places:
117 * 1) The AST, that is in instances of classes derived from Ast::Node.
118 * 2) The global storage for auxilliary source locations (created using Ast::theSourceLocationFactory).
119 * 3) Static variables in functions (only for "internal" locations constructed with FileID::build_internal).
120 * All other classes should only keep const SourceLocation & members. Any class that violates this rule
121 * and whose instances won't live for the rest of the program execution, is a potential source of use-after-free
122 * memory bugs.
124 * When building the AST, the scanner's SourceLocation instance (shapeslloc) obviously need to be copied each time
125 * a node is constructed. For that purpose, a special constructor taking an additional dummy bool argument is provided.
128 private:
129 /* Prevent accidental use of copy constructor. */
130 SourceLocation( const SourceLocation & orig );
131 public:
132 SourceLocation( ); /* A default constructor is required by Bison. Besides that, it should not be used! */
133 SourceLocation( const FileID * file ); /* New location for first position in file. */
134 SourceLocation( const SourceLocation & firstLoc, const Ast::SourceLocation & lastLoc ); /* New location spanning the ones given. */
135 /* Disguised copy constructor. Use only to construct copies that will live as long as the AST.
136 * The dummy argument is there to force the user of this constructor to think twice.
138 SourceLocation( const SourceLocation & orig, bool dummy );
139 /* Assigning source locations is considered relatively safe as long as the above rules about storage is followed.
140 * Just note that it is probably not a good idea to have const SourceLocation & references around pointing to the
141 * instance being assigned.
143 SourceLocation & operator = ( const SourceLocation & orig );
144 void swap( SourceLocation * other );
146 bool isUnknown( ) const;
147 bool contains( const SourceLocation & loc2 ) const;
148 friend std::ostream & operator << ( std::ostream & os, const SourceLocation & self );
150 void copy( std::ostream * os ) const;
151 Ast::Expression * findExpression( ) const;
154 class SourceLocationFactory
156 std::list< Ast::SourceLocation * > mem_;
157 public:
158 SourceLocationFactory( );
159 ~SourceLocationFactory( );
160 const Ast::SourceLocation & construct( const FileID * file );
161 const Ast::SourceLocation & construct_internal( const char * locationName ); /* Does not deep-copy locationName. */
164 extern const SourceLocation THE_UNKNOWN_LOCATION;
165 extern SourceLocationFactory theSourceLocationFactory;
167 std::ostream & operator << ( std::ostream & os, const SourceLocation & self );