1 /* CPP Library - traditional lexical analysis and macro expansion.
2 Copyright (C) 2002 Free Software Foundation, Inc.
3 Contributed by Neil Booth, May 2002
5 This program is free software; you can redistribute it and/or modify it
6 under the terms of the GNU General Public License as published by the
7 Free Software Foundation; either version 2, or (at your option) any
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
24 /* Lexing TODO: Handle -Wcomment, -C, maybe -CC, and space in escaped
25 newlines. Stop cpplex.c from recognizing comments, trigraphs and
26 directives during its lexing pass. */
28 static const uchar *handle_newline PARAMS ((cpp_reader *, const uchar *));
29 static const uchar *skip_escaped_newlines PARAMS ((cpp_reader *,
31 static cpp_hashnode *lex_identifier PARAMS ((cpp_reader *, const uchar *));
32 static const uchar *skip_comment PARAMS ((cpp_reader *, const uchar *));
33 static void scan_out_logical_line PARAMS ((cpp_reader *pfile));
34 static void check_output_buffer PARAMS ((cpp_reader *, size_t));
35 static void restore_buff PARAMS ((cpp_reader *));
37 /* Ensures we have N bytes' space in the output buffer, and
38 reallocates it if not. */
40 check_output_buffer (pfile, n)
44 if (n > (size_t) (pfile->trad_out_limit - pfile->trad_out_cur))
46 size_t size = pfile->trad_out_cur - pfile->trad_out_base;
47 size_t new_size = (size + n) * 3 / 2;
50 = (uchar *) xrealloc (pfile->trad_out_base, new_size);
51 pfile->trad_out_limit = pfile->trad_out_base + new_size;
52 pfile->trad_out_cur = pfile->trad_out_base + size;
56 /* To be called whenever a newline character is encountered in the
57 input file, at CUR. Handles DOS, MAC and Unix ends of line, and
58 returns the character after the newline sequence. */
60 handle_newline (pfile, cur)
65 if (cur[0] + cur[1] == '\r' + '\n')
70 /* CUR points to any character in the buffer, not necessarily a
71 backslash. Advances CUR until all escaped newlines are skipped,
72 and returns the new position. */
74 skip_escaped_newlines (pfile, cur)
78 while (*cur == '\\' && is_vspace (cur[1]))
79 cur = handle_newline (pfile, cur + 1);
84 /* CUR points to the character after the asterisk introducing a
85 comment. Returns the position after the comment. */
87 skip_comment (pfile, cur)
91 unsigned int from_line = pfile->line;
95 unsigned int c = *cur++;
98 cur = skip_escaped_newlines (pfile, cur);
105 else if (is_vspace (c))
106 cur = handle_newline (pfile, cur - 1);
107 else if (c == '\0' && cur - 1 == pfile->buffer->rlimit)
110 cpp_error_with_line (pfile, DL_ERROR, from_line, 0,
111 "unterminated comment");
119 /* Lexes and outputs an identifier starting at CUR, which is assumed
120 to point to a valid first character of an identifier. Returns
121 the hashnode, and updates trad_out_cur. */
122 static cpp_hashnode *
123 lex_identifier (pfile, cur)
128 uchar *out = pfile->trad_out_cur;
134 while (ISIDNUM (*cur));
135 cur = skip_escaped_newlines (pfile, cur);
137 while (ISIDNUM (*cur));
139 pfile->buffer->cur = cur;
140 len = out - pfile->trad_out_cur;
141 pfile->trad_out_cur = out;
142 return (cpp_hashnode *) ht_lookup (pfile->hash_table, pfile->trad_out_cur,
146 /* Overlays the true file buffer temporarily with text of length LEN
147 starting at START. The true buffer is restored upon calling
150 _cpp_overlay_buffer (pfile, start, len)
155 cpp_buffer *buffer = pfile->buffer;
157 buffer->saved_cur = buffer->cur;
158 buffer->saved_rlimit = buffer->rlimit;
159 buffer->saved_line_base = buffer->line_base;
162 buffer->line_base = start;
163 buffer->rlimit = start + len;
166 /* Restores a buffer overlaid by _cpp_overlay_buffer(). */
171 cpp_buffer *buffer = pfile->buffer;
173 buffer->cur = buffer->saved_cur;
174 buffer->rlimit = buffer->saved_rlimit;
175 buffer->line_base = buffer->saved_line_base;
178 /* Reads a logical line into the output buffer. Returns TRUE if there
179 is more text left in the buffer. */
181 _cpp_read_logical_line_trad (pfile)
185 unsigned int first_line;
187 restore_buff (pfile);
189 first_line = pfile->line = pfile->trad_line;
191 buffer = pfile->buffer;
192 if (buffer->cur == buffer->rlimit)
196 /* Don't pop the last buffer. */
199 stop = buffer->return_at_eof;
200 _cpp_pop_buffer (pfile);
207 pfile->trad_out_cur = pfile->trad_out_base;
208 scan_out_logical_line (pfile);
209 pfile->trad_line = pfile->line;
210 pfile->line = first_line;
211 _cpp_overlay_buffer (pfile, pfile->trad_out_base,
212 pfile->trad_out_cur - pfile->trad_out_base);
216 /* Copies the next logical line in the current buffer to the output
217 buffer. The output is guaranteed to terminate with a NUL
220 scan_out_logical_line (pfile)
223 cpp_buffer *buffer = pfile->buffer;
224 const uchar *cur = buffer->cur;
225 unsigned int c, quote = 0;
228 check_output_buffer (pfile, buffer->rlimit - cur);
229 out = pfile->trad_out_cur;
236 /* There are only a few entities we need to catch: comments,
237 identifiers, newlines, escaped newlines, # and '\0'. */
241 if (cur - 1 != buffer->rlimit)
244 if (!buffer->from_stage3)
245 cpp_error (pfile, DL_PEDWARN, "no newline at end of file");
249 case '\r': case '\n':
250 cur = handle_newline (pfile, cur - 1);
255 pfile->trad_out_cur = out;
267 if (is_vspace (*cur))
268 out--, cur = skip_escaped_newlines (pfile, cur - 1);
271 /* Skip escaped quotes here, it's easier than above, but
272 take care to first skip escaped newlines. */
273 cur = skip_escaped_newlines (pfile, cur);
274 if (*cur == '\\' || *cur == '"' || *cur == '\'')
280 /* Traditional CPP does not recognize comments within
284 cur = skip_escaped_newlines (pfile, cur);
286 out--, cur = skip_comment (pfile, cur + 1);
291 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
292 case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
293 case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
294 case 's': case 't': case 'u': case 'v': case 'w': case 'x':
296 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
297 case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
298 case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
299 case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
304 pfile->trad_out_cur = --out;
305 node = lex_identifier (pfile, cur - 1);
306 out = pfile->trad_out_cur;