1139804Simp/* CPP Library - directive only preprocessing for distributed compilation.
21541Srgrimes   Copyright (C) 2007
31541Srgrimes   Free Software Foundation, Inc.
41541Srgrimes   Contributed by Ollie Wild <aaw@google.com>.
51541Srgrimes
61541SrgrimesThis program is free software; you can redistribute it and/or modify it
71541Srgrimesunder the terms of the GNU General Public License as published by the
81541SrgrimesFree Software Foundation; either version 2, or (at your option) any
91541Srgrimeslater version.
101541Srgrimes
111541SrgrimesThis program is distributed in the hope that it will be useful,
121541Srgrimesbut WITHOUT ANY WARRANTY; without even the implied warranty of
131541SrgrimesMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
141541SrgrimesGNU General Public License for more details.
151541Srgrimes
161541SrgrimesYou should have received a copy of the GNU General Public License
171541Srgrimesalong with this program; if not, write to the Free Software
181541SrgrimesFoundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
191541Srgrimes
201541Srgrimes#include "config.h"
211541Srgrimes#include "system.h"
221541Srgrimes#include "cpplib.h"
231541Srgrimes#include "internal.h"
241541Srgrimes
251541Srgrimes/* DO (Directive only) flags. */
261541Srgrimes#define DO_BOL		 (1 << 0) /* At the beginning of a logical line. */
271541Srgrimes#define DO_STRING	 (1 << 1) /* In a string constant. */
281541Srgrimes#define DO_CHAR		 (1 << 2) /* In a character constant. */
291541Srgrimes#define DO_BLOCK_COMMENT (1 << 3) /* In a block comment. */
301541Srgrimes#define DO_LINE_COMMENT	 (1 << 4) /* In a single line "//-style" comment. */
311541Srgrimes
321541Srgrimes#define DO_LINE_SPECIAL (DO_STRING | DO_CHAR | DO_LINE_COMMENT)
331541Srgrimes#define DO_SPECIAL	(DO_LINE_SPECIAL | DO_BLOCK_COMMENT)
341541Srgrimes
351541Srgrimes/* Writes out the preprocessed file, handling spacing and paste
361541Srgrimes   avoidance issues.  */
37116182Sobrienvoid
38116182Sobrien_cpp_preprocess_dir_only (cpp_reader *pfile,
39116182Sobrien			  const struct _cpp_dir_only_callbacks *cb)
4013203Swollman{
41101127Srwatson  struct cpp_buffer *buffer;
4213203Swollman  const unsigned char *cur, *base, *next_line, *rlimit;
431541Srgrimes  cppchar_t c, last_c;
442112Swollman  unsigned flags;
4569664Speter  int lines, col;
46177785Skib  source_location loc;
4776166Smarkm
4889316Salfred restart:
491541Srgrimes  /* Buffer initialization ala _cpp_clean_line(). */
501541Srgrimes  buffer = pfile->buffer;
511541Srgrimes  buffer->cur_note = buffer->notes_used = 0;
521541Srgrimes  buffer->cur = buffer->line_base = buffer->next_line;
531541Srgrimes  buffer->need_line = false;
54141471Sjhb
55144613Sjeff  /* This isn't really needed.  It prevents a compiler warning, though. */
561541Srgrimes  loc = pfile->line_table->highest_line;
571541Srgrimes
581541Srgrimes  /* Scan initialization. */
591541Srgrimes  next_line = cur = base = buffer->cur;
60155334Srwatson  rlimit = buffer->rlimit;
61163606Srwatson  flags = DO_BOL;
62155334Srwatson  lines = 0;
6392751Sjeff  col = 1;
6432011Sbde
65155168Sjeff  for (last_c = '\n', c = *cur; cur < rlimit; last_c = c, c = *++cur, ++col)
66138345Sphk    {
67138345Sphk      /* Skip over escaped newlines. */
681541Srgrimes      if (__builtin_expect (c == '\\', false))
6969664Speter	{
7069664Speter	  const unsigned char *tmp = cur + 1;
7192751Sjeff
72166167Skib	  while (is_nvspace (*tmp) && tmp < rlimit)
73166167Skib	    tmp++;
74166167Skib	  if (*tmp == '\r')
75166167Skib	    tmp++;
7669664Speter	  if (*tmp == '\n' && tmp < rlimit)
7769664Speter	    {
7869664Speter	      CPP_INCREMENT_LINE (pfile, 0);
7969664Speter	      lines++;
80168138Srwatson	      col = 0;
81168138Srwatson	      cur = tmp;
8292654Sjeff	      c = last_c;
8392654Sjeff	      continue;
84168138Srwatson	    }
85168138Srwatson	}
86168138Srwatson
87176519Sattilio      if (__builtin_expect (last_c == '#', false) && !(flags & DO_SPECIAL))
8869664Speter	{
89177253Srwatson	  if (c != '#' && (flags & DO_BOL))
9069664Speter	  {
91183520Sjhb	    struct line_maps *line_table;
92144613Sjeff
93144613Sjeff	    if (!pfile->state.skipping && next_line != base)
94183519Sjhb	      cb->print_lines (lines, base, next_line - base);
95144613Sjeff
9669664Speter	    /* Prep things for directive handling. */
97161010Srwatson	    buffer->next_line = cur;
981541Srgrimes	    buffer->need_line = true;
991541Srgrimes	    _cpp_get_fresh_line (pfile);
1001541Srgrimes
1011541Srgrimes	    /* Ensure proper column numbering for generated error messages. */
1021541Srgrimes	    buffer->line_base -= col - 1;
1031541Srgrimes
1041541Srgrimes	    _cpp_handle_directive (pfile, 0 /* ignore indented */);
1051541Srgrimes
1061541Srgrimes	    /* Sanitize the line settings.  Duplicate #include's can mess
1071541Srgrimes	       things up. */
1081541Srgrimes	    line_table = pfile->line_table;
1091541Srgrimes	    line_table->highest_location = line_table->highest_line;
1101541Srgrimes
1111541Srgrimes	    /* The if block prevents us from outputing line information when
1121541Srgrimes	       the file ends with a directive and no newline.  Note that we
1131541Srgrimes	       must use pfile->buffer, not buffer. */
1141541Srgrimes	    if (pfile->buffer->cur != pfile->buffer->rlimit)
1151541Srgrimes	      cb->maybe_print_line (pfile->line_table->highest_line);
1161541Srgrimes
117161011Srwatson	    goto restart;
1181541Srgrimes	  }
119161011Srwatson
120161011Srwatson	  flags &= ~DO_BOL;
121161011Srwatson	  pfile->mi_valid = false;
1221541Srgrimes	}
1231541Srgrimes      else if (__builtin_expect (last_c == '/', false) \
1241541Srgrimes	       && !(flags & DO_SPECIAL) && c != '*' && c != '/')
1251541Srgrimes	{
12683366Sjulian	  /* If a previous slash is not starting a block comment, clear the
12783366Sjulian	     DO_BOL flag.  */
128140714Sjeff	  flags &= ~DO_BOL;
1291541Srgrimes	  pfile->mi_valid = false;
130150164Scsjp	}
131150164Scsjp
13291419Sjhb      switch (c)
13383366Sjulian	{
13442408Seivind	case '/':
13542453Seivind	  if ((flags & DO_BLOCK_COMMENT) && last_c == '*')
13642408Seivind	    {
13742453Seivind	      flags &= ~DO_BLOCK_COMMENT;
138144613Sjeff	      c = 0;
139144613Sjeff	    }
14083366Sjulian	  else if (!(flags & DO_SPECIAL) && last_c == '/')
1411541Srgrimes	    flags |= DO_LINE_COMMENT;
1421541Srgrimes	  else if (!(flags & DO_SPECIAL))
1431541Srgrimes	    /* Mark the position for possible error reporting. */
1441541Srgrimes	    LINEMAP_POSITION_FOR_COLUMN (loc, pfile->line_table, col);
1451541Srgrimes
1461541Srgrimes	  break;
147111119Simp
1481541Srgrimes	case '*':
1491541Srgrimes	  if (!(flags & DO_SPECIAL))
15036735Sdfr	    {
1511541Srgrimes	      if (last_c == '/')
1521541Srgrimes		flags |= DO_BLOCK_COMMENT;
15336735Sdfr	      else
15420069Sbde		{
155155334Srwatson		  flags &= ~DO_BOL;
156155334Srwatson		  pfile->mi_valid = false;
157155334Srwatson		}
158155334Srwatson	    }
159155334Srwatson
160155334Srwatson	  break;
16120069Sbde
16220069Sbde	case '\'':
16320069Sbde	case '"':
16420069Sbde	  {
16520069Sbde	    unsigned state = (c == '"') ? DO_STRING : DO_CHAR;
16620069Sbde
1671541Srgrimes	    if (!(flags & DO_SPECIAL))
16892751Sjeff	      {
169100613Srwatson		flags |= state;
170100613Srwatson		flags &= ~DO_BOL;
171100613Srwatson		pfile->mi_valid = false;
172100613Srwatson	      }
1731541Srgrimes	    else if ((flags & state) && last_c != '\\')
1741541Srgrimes	      flags &= ~state;
1751541Srgrimes
1761541Srgrimes	    break;
1771541Srgrimes	  }
17897994Sjhb
17997994Sjhb	case '\\':
18097994Sjhb	  {
18197994Sjhb	    if ((flags & (DO_STRING | DO_CHAR)) && last_c == '\\')
18297994Sjhb	      c = 0;
1831541Srgrimes
1841541Srgrimes	    if (!(flags & DO_SPECIAL))
1851541Srgrimes	      {
1861541Srgrimes		flags &= ~DO_BOL;
1871541Srgrimes		pfile->mi_valid = false;
188168355Srwatson	      }
18933360Sdyson
19051649Sphk	    break;
19133360Sdyson	  }
192185029Spjd
193185029Spjd	case '\n':
194185029Spjd	  CPP_INCREMENT_LINE (pfile, 0);
195185029Spjd	  lines++;
196185029Spjd	  col = 0;
197185029Spjd	  flags &= ~DO_LINE_SPECIAL;
198185029Spjd	  if (!(flags & DO_SPECIAL))
199185029Spjd	    flags |= DO_BOL;
200185029Spjd	  break;
201185029Spjd
202185029Spjd	case '#':
203185029Spjd	  next_line = cur;
204185029Spjd	  /* Don't update DO_BOL yet. */
205185029Spjd	  break;
206185029Spjd
207177785Skib	case ' ': case '\t': case '\f': case '\v': case '\0':
208177785Skib	  break;
209177785Skib
210177785Skib	default:
211177785Skib	  if (!(flags & DO_SPECIAL))
212177785Skib	    {
213177785Skib	      flags &= ~DO_BOL;
214177785Skib	      pfile->mi_valid = false;
215177785Skib	    }
216185029Spjd	  break;
217185029Spjd	}
218177785Skib    }
219177785Skib
220177785Skib  if (flags & DO_BLOCK_COMMENT)
221185029Spjd    cpp_error_with_line (pfile, CPP_DL_ERROR, loc, 0, "unterminated comment");
222185029Spjd
223185029Spjd  if (!pfile->state.skipping && cur != base)
224185029Spjd    cb->print_lines (lines, base, cur - base);
225185029Spjd
226177785Skib  _cpp_pop_buffer (pfile);
227140714Sjeff  if (pfile->buffer)
2281541Srgrimes    goto restart;
2291541Srgrimes}
2301541Srgrimes