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 -C, maybe -CC, and space in escaped newlines.
25 Stop cpplex.c from recognizing comments and directives during its
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')
67 pfile
->buffer
->line_base
= cur
+ 1;
71 /* CUR points to any character in the buffer, not necessarily a
72 backslash. Advances CUR until all escaped newlines are skipped,
73 and returns the new position. */
75 skip_escaped_newlines (pfile
, cur
)
79 while (*cur
== '\\' && is_vspace (cur
[1]))
80 cur
= handle_newline (pfile
, cur
+ 1);
85 /* CUR points to the character after the asterisk introducing a
86 comment. Returns the position after the comment. */
88 skip_comment (pfile
, cur
)
92 unsigned int from_line
= pfile
->line
;
93 unsigned int c
= 0, prevc
;
94 const uchar
*limit
= pfile
->buffer
->rlimit
;
105 if (*cur
== '*' && cur
[1] != '/'
106 && CPP_OPTION (pfile
, warn_comments
))
107 cpp_error_with_line (pfile
, DL_WARNING
, pfile
->line
, 0,
108 "\"/*\" within comment");
110 else if (is_vspace (c
))
111 cur
= handle_newline (pfile
, cur
- 1);
114 if (c
!= '/' || prevc
!= '*')
115 cpp_error_with_line (pfile
, DL_ERROR
, from_line
, 0,
116 "unterminated comment");
121 /* Lexes and outputs an identifier starting at CUR, which is assumed
122 to point to a valid first character of an identifier. Returns
123 the hashnode, and updates trad_out_cur. */
124 static cpp_hashnode
*
125 lex_identifier (pfile
, cur
)
130 uchar
*out
= pfile
->trad_out_cur
;
136 while (ISIDNUM (*cur
));
137 cur
= skip_escaped_newlines (pfile
, cur
);
139 while (ISIDNUM (*cur
));
141 pfile
->buffer
->cur
= cur
;
142 len
= out
- pfile
->trad_out_cur
;
143 pfile
->trad_out_cur
= out
;
144 return (cpp_hashnode
*) ht_lookup (pfile
->hash_table
, pfile
->trad_out_cur
,
148 /* Overlays the true file buffer temporarily with text of length LEN
149 starting at START. The true buffer is restored upon calling
152 _cpp_overlay_buffer (pfile
, start
, len
)
157 cpp_buffer
*buffer
= pfile
->buffer
;
159 buffer
->saved_cur
= buffer
->cur
;
160 buffer
->saved_rlimit
= buffer
->rlimit
;
161 buffer
->saved_line_base
= buffer
->line_base
;
164 buffer
->line_base
= start
;
165 buffer
->rlimit
= start
+ len
;
168 /* Restores a buffer overlaid by _cpp_overlay_buffer(). */
173 cpp_buffer
*buffer
= pfile
->buffer
;
175 buffer
->cur
= buffer
->saved_cur
;
176 buffer
->rlimit
= buffer
->saved_rlimit
;
177 buffer
->line_base
= buffer
->saved_line_base
;
180 /* Reads a logical line into the output buffer. Returns TRUE if there
181 is more text left in the buffer. */
183 _cpp_read_logical_line_trad (pfile
)
187 unsigned int first_line
;
189 restore_buff (pfile
);
191 first_line
= pfile
->line
= pfile
->trad_line
;
193 buffer
= pfile
->buffer
;
194 if (buffer
->cur
== buffer
->rlimit
)
198 /* Don't pop the last buffer. */
201 stop
= buffer
->return_at_eof
;
202 _cpp_pop_buffer (pfile
);
209 pfile
->trad_out_cur
= pfile
->trad_out_base
;
210 scan_out_logical_line (pfile
);
211 pfile
->trad_line
= pfile
->line
;
212 pfile
->line
= first_line
;
213 _cpp_overlay_buffer (pfile
, pfile
->trad_out_base
,
214 pfile
->trad_out_cur
- pfile
->trad_out_base
);
218 /* Copies the next logical line in the current buffer to the output
219 buffer. The output is guaranteed to terminate with a NUL
222 scan_out_logical_line (pfile
)
225 cpp_buffer
*buffer
= pfile
->buffer
;
226 const uchar
*cur
= buffer
->cur
;
227 unsigned int c
, quote
= 0;
230 check_output_buffer (pfile
, buffer
->rlimit
- cur
);
231 out
= pfile
->trad_out_cur
;
238 /* There are only a few entities we need to catch: comments,
239 identifiers, newlines, escaped newlines, # and '\0'. */
243 if (cur
- 1 != buffer
->rlimit
)
246 if (!buffer
->from_stage3
)
247 cpp_error (pfile
, DL_PEDWARN
, "no newline at end of file");
251 case '\r': case '\n':
252 cur
= handle_newline (pfile
, cur
- 1);
257 pfile
->trad_out_cur
= out
;
269 if (is_vspace (*cur
))
270 out
--, cur
= skip_escaped_newlines (pfile
, cur
- 1);
273 /* Skip escaped quotes here, it's easier than above, but
274 take care to first skip escaped newlines. */
275 cur
= skip_escaped_newlines (pfile
, cur
);
276 if (*cur
== '\\' || *cur
== '"' || *cur
== '\'')
282 /* Traditional CPP does not recognize comments within
286 cur
= skip_escaped_newlines (pfile
, cur
);
288 out
--, cur
= skip_comment (pfile
, cur
+ 1);
293 case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
294 case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
295 case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
296 case 's': case 't': case 'u': case 'v': case 'w': case 'x':
298 case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
299 case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
300 case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
301 case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
306 pfile
->trad_out_cur
= --out
;
307 node
= lex_identifier (pfile
, cur
- 1);
308 out
= pfile
->trad_out_cur
;