]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.bin/dtc/input_buffer.cc
Add ELF Tool Chain's ar(1) and elfdump(1) to contrib
[FreeBSD/FreeBSD.git] / usr.bin / dtc / input_buffer.cc
1 /*-
2  * Copyright (c) 2013 David Chisnall
3  * All rights reserved.
4  *
5  * This software was developed by SRI International and the University of
6  * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
7  * ("CTSRD"), as part of the DARPA CRASH research programme.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  *
30  * $FreeBSD$
31  */
32
33 #include "input_buffer.hh"
34 #include <ctype.h>
35 #include <limits.h>
36 #include <stdint.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40
41
42 #include <sys/stat.h>
43 #include <sys/mman.h>
44 #include <assert.h>
45
46 #ifndef MAP_PREFAULT_READ
47 #define MAP_PREFAULT_READ 0
48 #endif
49
50 namespace dtc
51 {
52
53 void
54 input_buffer::skip_spaces()
55 {
56         if (cursor >= size) { return; }
57         if (cursor < 0) { return; }
58         char c = buffer[cursor];
59         while ((c == ' ') || (c == '\t') || (c == '\n') || (c == '\f')
60                || (c == '\v') || (c == '\r'))
61         {
62                 cursor++;
63                 if (cursor > size)
64                 {
65                         c = '\0';
66                 }
67                 else
68                 {
69                         c = buffer[cursor];
70                 }
71         }
72 }
73
74 input_buffer
75 input_buffer::buffer_from_offset(int offset, int s)
76 {
77         if (s == 0)
78         {
79                 s = size - offset;
80         }
81         if (offset > size)
82         {
83                 return input_buffer();
84         }
85         if (s > (size-offset))
86         {
87                 return input_buffer();
88         }
89         return input_buffer(&buffer[offset], s);
90 }
91
92 bool
93 input_buffer::consume(const char *str)
94 {
95         int len = strlen(str);
96         if (len > size - cursor)
97         {
98                 return false;
99         }
100         else
101         {
102                 for (int i=0 ; i<len ; ++i)
103                 {
104                         if (str[i] != buffer[cursor + i])
105                         {
106                                 return false;
107                         }
108                 }
109                 cursor += len;
110                 return true;
111         }
112         return false;
113 }
114
115 bool
116 input_buffer::consume_integer(long long &outInt)
117 {
118         // The first character must be a digit.  Hex and octal strings
119         // are prefixed by 0 and 0x, respectively.
120         if (!isdigit((*this)[0]))
121         {
122                 return false;
123         }
124         char *end=0;
125         outInt = strtoll(&buffer[cursor], &end, 0);
126         if (end == &buffer[cursor])
127         {
128                 return false;
129         }
130         cursor = end - buffer;
131         return true;
132 }
133
134 bool
135 input_buffer::consume_hex_byte(uint8_t &outByte)
136 {
137         if (!ishexdigit((*this)[0]) && !ishexdigit((*this)[1]))
138         {
139                 return false;
140         }
141         outByte = (digittoint((*this)[0]) << 4) | digittoint((*this)[1]);
142         cursor += 2;
143         return true;
144 }
145
146 input_buffer&
147 input_buffer::next_token()
148 {
149         int start;
150         do {
151                 start = cursor;
152                 skip_spaces();
153                 // Parse /* comments
154                 if ((*this)[0] == '/' && (*this)[1] == '*')
155                 {
156                         // eat the start of the comment
157                         ++(*this);
158                         ++(*this);
159                         do {
160                                 // Find the ending * of */
161                                 while ((**this != '\0') && (**this != '*'))
162                                 {
163                                         ++(*this);
164                                 }
165                                 // Eat the *
166                                 ++(*this);
167                         } while ((**this != '\0') && (**this != '/'));
168                         // Eat the /
169                         ++(*this);
170                 }
171                 // Parse // comments and # comments
172                 if (((*this)[0] == '/' && (*this)[1] == '/') || 
173                      (*this)[0] == '#')
174                 {
175                         // eat the start of the comment
176                         ++(*this);
177                         ++(*this);
178                         // Find the ending of the line
179                         while (**this != '\n')
180                         {
181                                 ++(*this);
182                         }
183                         // Eat the \n
184                         ++(*this);
185                 }
186         } while (start != cursor);
187         return *this;
188 }
189
190 void
191 input_buffer::parse_error(const char *msg)
192 {
193         int line_count = 1;
194         int line_start = 0;
195         int line_end = cursor;
196         for (int i=cursor ; i>0 ; --i)
197         {
198                 if (buffer[i] == '\n')
199                 {
200                         line_count++;
201                         if (line_start == 0)
202                         {
203                                 line_start = i+1;
204                         }
205                 }
206         }
207         for (int i=cursor+1 ; i<size ; ++i)
208         {
209                 if (buffer[i] == '\n')
210                 {
211                         line_end = i;
212                         break;
213                 }
214         }
215         fprintf(stderr, "Error on line %d: %s\n", line_count, msg);
216         fwrite(&buffer[line_start], line_end-line_start, 1, stderr);
217         putc('\n', stderr);
218         for (int i=0 ; i<(cursor-line_start) ; ++i)
219         {
220                 char c = (buffer[i+line_start] == '\t') ? '\t' : ' ';
221                 putc(c, stderr);
222         }
223         putc('^', stderr);
224         putc('\n', stderr);
225 }
226 void
227 input_buffer::dump()
228 {
229         fprintf(stderr, "Current cursor: %d\n", cursor);
230         fwrite(&buffer[cursor], size-cursor, 1, stderr);
231 }
232
233 mmap_input_buffer::mmap_input_buffer(int fd) : input_buffer(0, 0)
234 {
235         struct stat sb;
236         if (fstat(fd, &sb))
237         {
238                 perror("Failed to stat file");
239         }
240         size = sb.st_size;
241         buffer = (const char*)mmap(0, size, PROT_READ,
242                 MAP_PREFAULT_READ, fd, 0);
243         if (buffer == 0)
244         {
245                 perror("Failed to mmap file");
246         }
247 }
248
249 mmap_input_buffer::~mmap_input_buffer()
250 {
251         if (buffer != 0)
252         {
253                 munmap((void*)buffer, size);
254         }
255 }
256
257 stream_input_buffer::stream_input_buffer() : input_buffer(0, 0)
258 {
259         int c;
260         while ((c = fgetc(stdin)) != EOF)
261         {
262                 b.push_back(c);
263         }
264         buffer = b.data();
265         size = b.size();
266 }
267
268 } // namespace dtc
269