1/* CPP Library - directive only preprocessing for distributed compilation. 2 Copyright (C) 2007-2015 Free Software Foundation, Inc. 3 Contributed by Ollie Wild <aaw@google.com>. 4 5This program is free software; you can redistribute it and/or modify it 6under the terms of the GNU General Public License as published by the 7Free Software Foundation; either version 3, or (at your option) any 8later version. 9 10This program is distributed in the hope that it will be useful, 11but WITHOUT ANY WARRANTY; without even the implied warranty of 12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13GNU General Public License for more details. 14 15You should have received a copy of the GNU General Public License 16along with this program; see the file COPYING3. If not see 17<http://www.gnu.org/licenses/>. */ 18 19#include "config.h" 20#include "system.h" 21#include "cpplib.h" 22#include "internal.h" 23 24/* DO (Directive only) flags. */ 25#define DO_BOL (1 << 0) /* At the beginning of a logical line. */ 26#define DO_STRING (1 << 1) /* In a string constant. */ 27#define DO_CHAR (1 << 2) /* In a character constant. */ 28#define DO_BLOCK_COMMENT (1 << 3) /* In a block comment. */ 29#define DO_LINE_COMMENT (1 << 4) /* In a single line "//-style" comment. */ 30 31#define DO_LINE_SPECIAL (DO_STRING | DO_CHAR | DO_LINE_COMMENT) 32#define DO_SPECIAL (DO_LINE_SPECIAL | DO_BLOCK_COMMENT) 33 34/* Writes out the preprocessed file, handling spacing and paste 35 avoidance issues. */ 36void 37_cpp_preprocess_dir_only (cpp_reader *pfile, 38 const struct _cpp_dir_only_callbacks *cb) 39{ 40 struct cpp_buffer *buffer; 41 const unsigned char *cur, *base, *next_line, *rlimit; 42 cppchar_t c, last_c; 43 unsigned flags; 44 linenum_type lines; 45 int col; 46 source_location loc; 47 48 restart: 49 /* Buffer initialization ala _cpp_clean_line(). */ 50 buffer = pfile->buffer; 51 buffer->cur_note = buffer->notes_used = 0; 52 buffer->cur = buffer->line_base = buffer->next_line; 53 buffer->need_line = false; 54 55 /* This isn't really needed. It prevents a compiler warning, though. */ 56 loc = pfile->line_table->highest_line; 57 58 /* Scan initialization. */ 59 next_line = cur = base = buffer->cur; 60 rlimit = buffer->rlimit; 61 flags = DO_BOL; 62 lines = 0; 63 col = 1; 64 65 for (last_c = '\n', c = *cur; cur < rlimit; last_c = c, c = *++cur, ++col) 66 { 67 /* Skip over escaped newlines. */ 68 if (__builtin_expect (c == '\\', false)) 69 { 70 const unsigned char *tmp = cur + 1; 71 72 while (is_nvspace (*tmp) && tmp < rlimit) 73 tmp++; 74 if (*tmp == '\r') 75 tmp++; 76 if (*tmp == '\n' && tmp < rlimit) 77 { 78 CPP_INCREMENT_LINE (pfile, 0); 79 lines++; 80 col = 0; 81 cur = tmp; 82 c = last_c; 83 continue; 84 } 85 } 86 87 if (__builtin_expect (last_c == '#', false) && !(flags & DO_SPECIAL)) 88 { 89 if (c != '#' && (flags & DO_BOL)) 90 { 91 struct line_maps *line_table; 92 93 if (!pfile->state.skipping && next_line != base) 94 cb->print_lines (lines, base, next_line - base); 95 96 /* Prep things for directive handling. */ 97 buffer->next_line = cur; 98 buffer->need_line = true; 99 _cpp_get_fresh_line (pfile); 100 101 /* Ensure proper column numbering for generated error messages. */ 102 buffer->line_base -= col - 1; 103 104 _cpp_handle_directive (pfile, 0 /* ignore indented */); 105 106 /* Sanitize the line settings. Duplicate #include's can mess 107 things up. */ 108 line_table = pfile->line_table; 109 line_table->highest_location = line_table->highest_line; 110 111 /* The if block prevents us from outputing line information when 112 the file ends with a directive and no newline. Note that we 113 must use pfile->buffer, not buffer. */ 114 if (pfile->buffer->next_line < pfile->buffer->rlimit) 115 cb->maybe_print_line (pfile->line_table->highest_line); 116 117 goto restart; 118 } 119 120 flags &= ~DO_BOL; 121 pfile->mi_valid = false; 122 } 123 else if (__builtin_expect (last_c == '/', false) \ 124 && !(flags & DO_SPECIAL) && c != '*' && c != '/') 125 { 126 /* If a previous slash is not starting a block comment, clear the 127 DO_BOL flag. */ 128 flags &= ~DO_BOL; 129 pfile->mi_valid = false; 130 } 131 132 switch (c) 133 { 134 case '/': 135 if ((flags & DO_BLOCK_COMMENT) && last_c == '*') 136 { 137 flags &= ~DO_BLOCK_COMMENT; 138 c = 0; 139 } 140 else if (!(flags & DO_SPECIAL) && last_c == '/') 141 flags |= DO_LINE_COMMENT; 142 else if (!(flags & DO_SPECIAL)) 143 /* Mark the position for possible error reporting. */ 144 loc = linemap_position_for_column (pfile->line_table, col); 145 146 break; 147 148 case '*': 149 if (!(flags & DO_SPECIAL)) 150 { 151 if (last_c == '/') 152 flags |= DO_BLOCK_COMMENT; 153 else 154 { 155 flags &= ~DO_BOL; 156 pfile->mi_valid = false; 157 } 158 } 159 160 break; 161 162 case '\'': 163 case '"': 164 { 165 unsigned state = (c == '"') ? DO_STRING : DO_CHAR; 166 167 if (!(flags & DO_SPECIAL)) 168 { 169 flags |= state; 170 flags &= ~DO_BOL; 171 pfile->mi_valid = false; 172 } 173 else if ((flags & state) && last_c != '\\') 174 flags &= ~state; 175 176 break; 177 } 178 179 case '\\': 180 { 181 if ((flags & (DO_STRING | DO_CHAR)) && last_c == '\\') 182 c = 0; 183 184 if (!(flags & DO_SPECIAL)) 185 { 186 flags &= ~DO_BOL; 187 pfile->mi_valid = false; 188 } 189 190 break; 191 } 192 193 case '\n': 194 CPP_INCREMENT_LINE (pfile, 0); 195 lines++; 196 col = 0; 197 flags &= ~DO_LINE_SPECIAL; 198 if (!(flags & DO_SPECIAL)) 199 flags |= DO_BOL; 200 break; 201 202 case '#': 203 next_line = cur; 204 /* Don't update DO_BOL yet. */ 205 break; 206 207 case ' ': case '\t': case '\f': case '\v': case '\0': 208 break; 209 210 default: 211 if (!(flags & DO_SPECIAL)) 212 { 213 flags &= ~DO_BOL; 214 pfile->mi_valid = false; 215 } 216 break; 217 } 218 } 219 220 if (flags & DO_BLOCK_COMMENT) 221 cpp_error_with_line (pfile, CPP_DL_ERROR, loc, 0, "unterminated comment"); 222 223 if (!pfile->state.skipping && cur != base) 224 { 225 /* If the file was not newline terminated, add rlimit, which is 226 guaranteed to point to a newline, to the end of our range. */ 227 if (cur[-1] != '\n') 228 { 229 cur++; 230 CPP_INCREMENT_LINE (pfile, 0); 231 lines++; 232 } 233 234 cb->print_lines (lines, base, cur - base); 235 } 236 237 _cpp_pop_buffer (pfile); 238 if (pfile->buffer) 239 goto restart; 240} 241