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