1258501Spfg/* CPP Library - directive only preprocessing for distributed compilation. 2258501Spfg Copyright (C) 2007 3258501Spfg Free Software Foundation, Inc. 4258501Spfg Contributed by Ollie Wild <aaw@google.com>. 5258501Spfg 6258501SpfgThis program is free software; you can redistribute it and/or modify it 7258501Spfgunder the terms of the GNU General Public License as published by the 8258501SpfgFree Software Foundation; either version 2, or (at your option) any 9258501Spfglater version. 10258501Spfg 11258501SpfgThis program is distributed in the hope that it will be useful, 12258501Spfgbut WITHOUT ANY WARRANTY; without even the implied warranty of 13258501SpfgMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14258501SpfgGNU General Public License for more details. 15258501Spfg 16258501SpfgYou should have received a copy of the GNU General Public License 17258501Spfgalong with this program; if not, write to the Free Software 18258501SpfgFoundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ 19258501Spfg 20258501Spfg#include "config.h" 21258501Spfg#include "system.h" 22258501Spfg#include "cpplib.h" 23258501Spfg#include "internal.h" 24258501Spfg 25258501Spfg/* DO (Directive only) flags. */ 26258501Spfg#define DO_BOL (1 << 0) /* At the beginning of a logical line. */ 27258501Spfg#define DO_STRING (1 << 1) /* In a string constant. */ 28258501Spfg#define DO_CHAR (1 << 2) /* In a character constant. */ 29258501Spfg#define DO_BLOCK_COMMENT (1 << 3) /* In a block comment. */ 30258501Spfg#define DO_LINE_COMMENT (1 << 4) /* In a single line "//-style" comment. */ 31258501Spfg 32258501Spfg#define DO_LINE_SPECIAL (DO_STRING | DO_CHAR | DO_LINE_COMMENT) 33258501Spfg#define DO_SPECIAL (DO_LINE_SPECIAL | DO_BLOCK_COMMENT) 34258501Spfg 35258501Spfg/* Writes out the preprocessed file, handling spacing and paste 36258501Spfg avoidance issues. */ 37258501Spfgvoid 38258501Spfg_cpp_preprocess_dir_only (cpp_reader *pfile, 39258501Spfg const struct _cpp_dir_only_callbacks *cb) 40258501Spfg{ 41258501Spfg struct cpp_buffer *buffer; 42258501Spfg const unsigned char *cur, *base, *next_line, *rlimit; 43258501Spfg cppchar_t c, last_c; 44258501Spfg unsigned flags; 45258501Spfg int lines, col; 46258501Spfg source_location loc; 47258501Spfg 48258501Spfg restart: 49258501Spfg /* Buffer initialization ala _cpp_clean_line(). */ 50258501Spfg buffer = pfile->buffer; 51258501Spfg buffer->cur_note = buffer->notes_used = 0; 52258501Spfg buffer->cur = buffer->line_base = buffer->next_line; 53258501Spfg buffer->need_line = false; 54258501Spfg 55258501Spfg /* This isn't really needed. It prevents a compiler warning, though. */ 56258501Spfg loc = pfile->line_table->highest_line; 57258501Spfg 58258501Spfg /* Scan initialization. */ 59258501Spfg next_line = cur = base = buffer->cur; 60258501Spfg rlimit = buffer->rlimit; 61258501Spfg flags = DO_BOL; 62258501Spfg lines = 0; 63258501Spfg col = 1; 64258501Spfg 65258501Spfg for (last_c = '\n', c = *cur; cur < rlimit; last_c = c, c = *++cur, ++col) 66258501Spfg { 67258501Spfg /* Skip over escaped newlines. */ 68258501Spfg if (__builtin_expect (c == '\\', false)) 69258501Spfg { 70258501Spfg const unsigned char *tmp = cur + 1; 71258501Spfg 72258501Spfg while (is_nvspace (*tmp) && tmp < rlimit) 73258501Spfg tmp++; 74258501Spfg if (*tmp == '\r') 75258501Spfg tmp++; 76258501Spfg if (*tmp == '\n' && tmp < rlimit) 77258501Spfg { 78258501Spfg CPP_INCREMENT_LINE (pfile, 0); 79258501Spfg lines++; 80258501Spfg col = 0; 81258501Spfg cur = tmp; 82258501Spfg c = last_c; 83258501Spfg continue; 84258501Spfg } 85258501Spfg } 86258501Spfg 87258501Spfg if (__builtin_expect (last_c == '#', false) && !(flags & DO_SPECIAL)) 88258501Spfg { 89258501Spfg if (c != '#' && (flags & DO_BOL)) 90258501Spfg { 91258501Spfg struct line_maps *line_table; 92258501Spfg 93258501Spfg if (!pfile->state.skipping && next_line != base) 94258501Spfg cb->print_lines (lines, base, next_line - base); 95258501Spfg 96258501Spfg /* Prep things for directive handling. */ 97258501Spfg buffer->next_line = cur; 98258501Spfg buffer->need_line = true; 99258501Spfg _cpp_get_fresh_line (pfile); 100258501Spfg 101258501Spfg /* Ensure proper column numbering for generated error messages. */ 102258501Spfg buffer->line_base -= col - 1; 103258501Spfg 104258501Spfg _cpp_handle_directive (pfile, 0 /* ignore indented */); 105258501Spfg 106258501Spfg /* Sanitize the line settings. Duplicate #include's can mess 107258501Spfg things up. */ 108258501Spfg line_table = pfile->line_table; 109258501Spfg line_table->highest_location = line_table->highest_line; 110258501Spfg 111258501Spfg /* The if block prevents us from outputing line information when 112258501Spfg the file ends with a directive and no newline. Note that we 113258501Spfg must use pfile->buffer, not buffer. */ 114258501Spfg if (pfile->buffer->cur != pfile->buffer->rlimit) 115258501Spfg cb->maybe_print_line (pfile->line_table->highest_line); 116258501Spfg 117258501Spfg goto restart; 118258501Spfg } 119258501Spfg 120258501Spfg flags &= ~DO_BOL; 121258501Spfg pfile->mi_valid = false; 122258501Spfg } 123258501Spfg else if (__builtin_expect (last_c == '/', false) \ 124258501Spfg && !(flags & DO_SPECIAL) && c != '*' && c != '/') 125258501Spfg { 126258501Spfg /* If a previous slash is not starting a block comment, clear the 127258501Spfg DO_BOL flag. */ 128258501Spfg flags &= ~DO_BOL; 129258501Spfg pfile->mi_valid = false; 130258501Spfg } 131258501Spfg 132258501Spfg switch (c) 133258501Spfg { 134258501Spfg case '/': 135258501Spfg if ((flags & DO_BLOCK_COMMENT) && last_c == '*') 136258501Spfg { 137258501Spfg flags &= ~DO_BLOCK_COMMENT; 138258501Spfg c = 0; 139258501Spfg } 140258501Spfg else if (!(flags & DO_SPECIAL) && last_c == '/') 141258501Spfg flags |= DO_LINE_COMMENT; 142258501Spfg else if (!(flags & DO_SPECIAL)) 143258501Spfg /* Mark the position for possible error reporting. */ 144258501Spfg LINEMAP_POSITION_FOR_COLUMN (loc, pfile->line_table, col); 145258501Spfg 146258501Spfg break; 147258501Spfg 148258501Spfg case '*': 149258501Spfg if (!(flags & DO_SPECIAL)) 150258501Spfg { 151258501Spfg if (last_c == '/') 152258501Spfg flags |= DO_BLOCK_COMMENT; 153258501Spfg else 154258501Spfg { 155258501Spfg flags &= ~DO_BOL; 156258501Spfg pfile->mi_valid = false; 157258501Spfg } 158258501Spfg } 159258501Spfg 160258501Spfg break; 161258501Spfg 162258501Spfg case '\'': 163258501Spfg case '"': 164258501Spfg { 165258501Spfg unsigned state = (c == '"') ? DO_STRING : DO_CHAR; 166258501Spfg 167258501Spfg if (!(flags & DO_SPECIAL)) 168258501Spfg { 169258501Spfg flags |= state; 170258501Spfg flags &= ~DO_BOL; 171258501Spfg pfile->mi_valid = false; 172258501Spfg } 173258501Spfg else if ((flags & state) && last_c != '\\') 174258501Spfg flags &= ~state; 175258501Spfg 176258501Spfg break; 177258501Spfg } 178258501Spfg 179258501Spfg case '\\': 180258501Spfg { 181258501Spfg if ((flags & (DO_STRING | DO_CHAR)) && last_c == '\\') 182258501Spfg c = 0; 183258501Spfg 184258501Spfg if (!(flags & DO_SPECIAL)) 185258501Spfg { 186258501Spfg flags &= ~DO_BOL; 187258501Spfg pfile->mi_valid = false; 188258501Spfg } 189258501Spfg 190258501Spfg break; 191258501Spfg } 192258501Spfg 193258501Spfg case '\n': 194258501Spfg CPP_INCREMENT_LINE (pfile, 0); 195258501Spfg lines++; 196258501Spfg col = 0; 197258501Spfg flags &= ~DO_LINE_SPECIAL; 198258501Spfg if (!(flags & DO_SPECIAL)) 199258501Spfg flags |= DO_BOL; 200258501Spfg break; 201258501Spfg 202258501Spfg case '#': 203258501Spfg next_line = cur; 204258501Spfg /* Don't update DO_BOL yet. */ 205258501Spfg break; 206258501Spfg 207258501Spfg case ' ': case '\t': case '\f': case '\v': case '\0': 208258501Spfg break; 209258501Spfg 210258501Spfg default: 211258501Spfg if (!(flags & DO_SPECIAL)) 212258501Spfg { 213258501Spfg flags &= ~DO_BOL; 214258501Spfg pfile->mi_valid = false; 215258501Spfg } 216258501Spfg break; 217258501Spfg } 218258501Spfg } 219258501Spfg 220258501Spfg if (flags & DO_BLOCK_COMMENT) 221258501Spfg cpp_error_with_line (pfile, CPP_DL_ERROR, loc, 0, "unterminated comment"); 222258501Spfg 223258501Spfg if (!pfile->state.skipping && cur != base) 224258501Spfg cb->print_lines (lines, base, cur - base); 225258501Spfg 226258501Spfg _cpp_pop_buffer (pfile); 227258501Spfg if (pfile->buffer) 228258501Spfg goto restart; 229258501Spfg} 230