]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.bin/dtc/input_buffer.cc
Import new (BSDL) device tree compiler. Now built by default, so that it can't
[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 <string.h>
35 #include <stdint.h>
36
37 #include <sys/stat.h>
38 #include <sys/mman.h>
39 #include <assert.h>
40
41 namespace dtc
42 {
43
44 void
45 input_buffer::skip_spaces()
46 {
47         if (cursor >= size) { return; }
48         if (cursor < 0) { return; }
49         char c = buffer[cursor];
50         while ((c == ' ') || (c == '\t') || (c == '\n') || (c == '\f')
51                || (c == '\v') || (c == '\r'))
52         {
53                 cursor++;
54                 if (cursor > size)
55                 {
56                         c = '\0';
57                 }
58                 else
59                 {
60                         c = buffer[cursor];
61                 }
62         }
63 }
64
65 input_buffer
66 input_buffer::buffer_from_offset(int offset, int s)
67 {
68         if (s == 0)
69         {
70                 s = size - offset;
71         }
72         if (offset > size)
73         {
74                 return input_buffer();
75         }
76         if (s > (size-offset))
77         {
78                 return input_buffer();
79         }
80         return input_buffer(&buffer[offset], s);
81 }
82
83 bool
84 input_buffer::consume(const char *str)
85 {
86         int len = strlen(str);
87         if (len > size - cursor)
88         {
89                 return false;
90         }
91         else
92         {
93                 for (int i=0 ; i<len ; ++i)
94                 {
95                         if (str[i] != buffer[cursor + i])
96                         {
97                                 return false;
98                         }
99                 }
100                 cursor += len;
101                 return true;
102         }
103         return false;
104 }
105
106 bool
107 input_buffer::consume_integer(long long &outInt)
108 {
109         // The first character must be a digit.  Hex and octal strings
110         // are prefixed by 0 and 0x, respectively.
111         if (!isdigit((*this)[0]))
112         {
113                 return false;
114         }
115         char *end=0;
116         outInt = strtoll(&buffer[cursor], &end, 0);
117         if (end == &buffer[cursor])
118         {
119                 return false;
120         }
121         cursor = end - buffer;
122         return true;
123 }
124
125 bool
126 input_buffer::consume_hex_byte(uint8_t &outByte)
127 {
128         if (!ishexdigit((*this)[0]) && !ishexdigit((*this)[1]))
129         {
130                 return false;
131         }
132         outByte = (digittoint((*this)[0]) << 4) | digittoint((*this)[1]);
133         cursor += 2;
134         return true;
135 }
136
137 input_buffer&
138 input_buffer::next_token()
139 {
140         int start;
141         do {
142                 start = cursor;
143                 skip_spaces();
144                 // Parse /* comments
145                 if (((*this)[0] == '/') && ((*this)[1] == '*'))
146                 {
147                         // eat the start of the comment
148                         ++(*this);
149                         ++(*this);
150                         do {
151                                 // Find the ending * of */
152                                 while ((**this != '\0') && (**this != '*'))
153                                 {
154                                         ++(*this);
155                                 }
156                                 // Eat the *
157                                 ++(*this);
158                         } while ((**this != '\0') && (**this != '/'));
159                         // Eat the /
160                         ++(*this);
161                 }
162                 // Parse // comments
163                 if (((*this)[0] == '/') && ((*this)[1] == '/'))
164                 {
165                         // eat the start of the comment
166                         ++(*this);
167                         ++(*this);
168                         // Find the ending * of */
169                         while (**this != '\n')
170                         {
171                                 ++(*this);
172                         }
173                         // Eat the \n
174                         ++(*this);
175                 }
176         } while (start != cursor);
177         return *this;
178 }
179
180 void
181 input_buffer::parse_error(const char *msg)
182 {
183         int line_count = 1;
184         int line_start = 0;
185         int line_end = cursor;
186         for (int i=cursor ; i>0 ; --i)
187         {
188                 if (buffer[i] == '\n')
189                 {
190                         line_count++;
191                         if (line_start == 0)
192                         {
193                                 line_start = i+1;
194                         }
195                 }
196         }
197         for (int i=cursor+1 ; i<size ; ++i)
198         {
199                 if (buffer[i] == '\n')
200                 {
201                         line_end = i;
202                         break;
203                 }
204         }
205         fprintf(stderr, "Error on line %d: %s\n", line_count, msg);
206         fwrite(&buffer[line_start], line_end-line_start, 1, stderr);
207         putc('\n', stderr);
208         for (int i=0 ; i<(cursor-line_start) ; ++i)
209         {
210                 putc(' ', stderr);
211         }
212         putc('^', stderr);
213         putc('\n', stderr);
214 }
215 void
216 input_buffer::dump()
217 {
218         fprintf(stderr, "Current cursor: %d\n", cursor);
219         fwrite(&buffer[cursor], size-cursor, 1, stderr);
220 }
221
222 mmap_input_buffer::mmap_input_buffer(int fd) : input_buffer(0, 0)
223 {
224         struct stat sb;
225         if (fstat(fd, &sb))
226         {
227                 perror("Failed to stat file");
228         }
229         size = sb.st_size;
230         buffer = (const char*)mmap(0, size, PROT_READ,
231                 MAP_PREFAULT_READ, fd, 0);
232         if (buffer == 0)
233         {
234                 perror("Failed to mmap file");
235         }
236 }
237
238 mmap_input_buffer::~mmap_input_buffer()
239 {
240         if (buffer != 0)
241         {
242                 munmap((void*)buffer, size);
243         }
244 }
245
246 stream_input_buffer::stream_input_buffer() : input_buffer(0, 0)
247 {
248         int c;
249         while ((c = fgetc(stdin)) != EOF)
250         {
251                 b.push_back(c);
252         }
253         buffer = b.data();
254         size = b.size();
255 }
256
257 } // namespace dtc
258