@@ -94,50 +94,64 @@ struct LocationManager {
9494 //
9595 //
9696 //
97- std::vector<uint32_t > out_start; // consecutive intervals in the output code
98- std::vector<uint32_t > in_start; // start + size in the original code
99- std::vector<uint32_t > in_newlines; // position of all \n in the original code
97+ struct FileLocations {
98+ std::vector<uint32_t > out_start; // consecutive intervals in the output code
99+ std::vector<uint32_t > in_start; // start + size in the original code
100+ std::vector<uint32_t > in_newlines; // position of all \n in the original code
100101
101- // For preprocessor (if preprocessor==true).
102- // TODO: design a common structure, that also works with #include, that
103- // has these mappings for each file
104- bool preprocessor = false ;
105- std::string in_filename;
106- uint32_t current_line=0 ;
107- std::vector<uint32_t > out_start0; // consecutive intervals in the output code
108- std::vector<uint32_t > in_start0; // start + size in the original code
109- std::vector<uint32_t > in_size0; // Size of the `in` interval
110- std::vector<uint32_t > interval_type0; // 0 .... 1:1; 1 ... many to many;
111- std::vector<uint32_t > in_newlines0; // position of all \n in the original code
112- // std::vector<uint32_t> filename_id; // file name for each interval, ID
113- // std::vector<std::string> filenames; // filenames lookup for an ID
102+ // For preprocessor (if preprocessor==true).
103+ // TODO: design a common structure, that also works with #include, that
104+ // has these mappings for each file
105+ bool preprocessor = false ;
106+ std::string in_filename;
107+ uint32_t current_line=0 ;
108+ std::vector<uint32_t > out_start0; // consecutive intervals in the output code
109+ std::vector<uint32_t > in_start0; // start + size in the original code
110+ std::vector<uint32_t > in_size0; // Size of the `in` interval
111+ std::vector<uint32_t > interval_type0; // 0 .... 1:1; 1 ... many to many;
112+ std::vector<uint32_t > in_newlines0; // position of all \n in the original code
113+ };
114+ std::vector<FileLocations> files;
115+ // Location is continued for the imported files, i.e.,if the new file is
116+ // imported then the location starts from the size of the previous file.
117+ // For example: file_ends = [120, 200, 350]
118+ std::vector<uint32_t > file_ends; // position of all ends of files
119+ // For a given Location, we use the `file_ends` and `bisection` to determine
120+ // the file (files' index), which the location is from. Then we use this index into
121+ // the `files` vector and use `in_newlines` and other information to
122+ // determine the line and column inside this file, and the `in_filename`
123+ // field to determine the filename. This happens when the diagnostic is
124+ // printed.
114125
115126 // Converts a position in the output code to a position in the original code
116127 // Every character in the output code has a corresponding location in the
117128 // original code, so this function always succeeds
118129 uint32_t output_to_input_pos (uint32_t out_pos, bool show_last) const {
119- if (out_start.size () == 0 ) return 0 ;
120- uint32_t interval = bisection (out_start, out_pos)-1 ;
121- uint32_t rel_pos = out_pos - out_start[interval];
122- uint32_t in_pos = in_start[interval] + rel_pos;
123- if (preprocessor) {
130+ // Determine where the error is from using position, i.e., loc
131+ uint32_t index = bisection (file_ends, out_pos);
132+ if (index == file_ends.size ()) index -= 1 ;
133+ if (files[index].out_start .size () == 0 ) return 0 ;
134+ uint32_t interval = bisection (files[index].out_start , out_pos)-1 ;
135+ uint32_t rel_pos = out_pos - files[index].out_start [interval];
136+ uint32_t in_pos = files[index].in_start [interval] + rel_pos;
137+ if (files[index].preprocessor ) {
124138 // If preprocessor was used, do one more remapping
125- uint32_t interval0 = bisection (out_start0, in_pos)-1 ;
126- if (interval_type0[interval0] == 0 ) {
139+ uint32_t interval0 = bisection (files[index]. out_start0 , in_pos)-1 ;
140+ if (files[index]. interval_type0 [interval0] == 0 ) {
127141 // 1:1 interval
128- uint32_t rel_pos0 = in_pos - out_start0[interval0];
129- uint32_t in_pos0 = in_start0[interval0] + rel_pos0;
142+ uint32_t rel_pos0 = in_pos - files[index]. out_start0 [interval0];
143+ uint32_t in_pos0 = files[index]. in_start0 [interval0] + rel_pos0;
130144 return in_pos0;
131145 } else {
132146 // many to many interval
133147 uint32_t in_pos0;
134- if (in_pos == out_start0[interval0+1 ]-1 || show_last) {
148+ if (in_pos == files[index]. out_start0 [interval0+1 ]-1 || show_last) {
135149 // The end of the interval in "out" code
136150 // Return the end of the interval in "in" code
137- in_pos0 = in_start0[interval0]+in_size0[interval0]-1 ;
151+ in_pos0 = files[index]. in_start0 [interval0]+files[index]. in_size0 [interval0]-1 ;
138152 } else {
139153 // Otherwise return the beginning of the interval in "in"
140- in_pos0 = in_start0[interval0];
154+ in_pos0 = files[index]. in_start0 [interval0];
141155 }
142156 return in_pos0;
143157 }
@@ -150,12 +164,19 @@ struct LocationManager {
150164 // `position` starts from 0
151165 // `line` and `col` starts from 1
152166 // `in_newlines` starts from 0
153- void pos_to_linecol (uint32_t position, uint32_t &line, uint32_t &col) const {
167+ void pos_to_linecol (uint32_t position, uint32_t &line, uint32_t &col,
168+ std::string &filename) const {
169+ // Determine where the error is from using position, i.e., loc
170+ uint32_t index = bisection (file_ends, position);
171+ if (index == file_ends.size ()) index -= 1 ;
172+ filename = files[index].in_filename ;
173+ // Get the actual location by subtracting the previous file size.
174+ if (index > 0 ) position -= file_ends[index - 1 ];
154175 const std::vector<uint32_t > *newlines;
155- if (preprocessor) {
156- newlines = &in_newlines0;
176+ if (files[index]. preprocessor ) {
177+ newlines = &files[index]. in_newlines0 ;
157178 } else {
158- newlines = &in_newlines;
179+ newlines = &files[index]. in_newlines ;
159180 }
160181 int32_t interval = bisection (*newlines, position);
161182 if (interval >= 1 && position == (*newlines)[interval-1 ]) {
@@ -179,9 +200,9 @@ struct LocationManager {
179200
180201 void init_simple (const std::string &input) {
181202 uint32_t n = input.size ();
182- out_start = {0 , n};
183- in_start = {0 , n};
184- get_newlines (input, in_newlines);
203+ files. back (). out_start = {0 , n};
204+ files. back (). in_start = {0 , n};
205+ get_newlines (input, files. back (). in_newlines );
185206 }
186207
187208};
0 commit comments