OSDN Git Service

* Makefile.in: Update for cpptrad.c.
[pf3gnuchains/gcc-fork.git] / gcc / cpptrad.c
1 /* CPP Library - traditional lexical analysis and macro expansion.
2    Copyright (C) 2002 Free Software Foundation, Inc.
3    Contributed by Neil Booth, May 2002
4
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
8 later version.
9
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.
14
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.  */
18
19 #include "config.h"
20 #include "system.h"
21 #include "cpplib.h"
22 #include "cpphash.h"
23
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.  */
27
28 static const uchar *handle_newline PARAMS ((cpp_reader *, const uchar *));
29 static const uchar *skip_escaped_newlines PARAMS ((cpp_reader *,
30                                                    const uchar *));
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 *));
36
37 /* Ensures we have N bytes' space in the output buffer, and
38    reallocates it if not.  */
39 static void
40 check_output_buffer (pfile, n)
41      cpp_reader *pfile;
42      size_t n;
43 {
44   if (n > (size_t) (pfile->trad_out_limit - pfile->trad_out_cur))
45     {
46       size_t size = pfile->trad_out_cur - pfile->trad_out_base;
47       size_t new_size = (size + n) * 3 / 2;
48
49       pfile->trad_out_base
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;
53     }
54 }
55
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.  */
59 static const uchar *
60 handle_newline (pfile, cur)
61      cpp_reader *pfile;
62      const uchar *cur;
63 {
64   pfile->line++;
65   if (cur[0] + cur[1] == '\r' + '\n')
66     cur++;
67   return cur + 1;
68 }
69
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.  */
73 static const uchar *
74 skip_escaped_newlines (pfile, cur)
75      cpp_reader *pfile;
76      const uchar *cur;
77 {
78   while (*cur == '\\' && is_vspace (cur[1]))
79     cur = handle_newline (pfile, cur + 1);
80
81   return cur;
82 }
83
84 /* CUR points to the character after the asterisk introducing a
85    comment.  Returns the position after the comment.  */
86 static const uchar *
87 skip_comment (pfile, cur)
88      cpp_reader *pfile;
89      const uchar *cur;
90 {
91   unsigned int from_line = pfile->line;
92
93   for (;;)
94     {
95       unsigned int c = *cur++;
96       if (c == '*')
97         {
98           cur = skip_escaped_newlines (pfile, cur);
99           if (*cur == '/')
100             {
101               cur++;
102               break;
103             }
104         }
105       else if (is_vspace (c))
106         cur = handle_newline (pfile, cur - 1);
107       else if (c == '\0' && cur - 1 == pfile->buffer->rlimit)
108         {
109           cur--;
110           cpp_error_with_line (pfile, DL_ERROR, from_line, 0,
111                                "unterminated comment");
112           break;
113         }
114     }
115
116   return cur;
117 }
118
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)
124      cpp_reader *pfile;
125      const uchar *cur;
126 {
127   size_t len;
128   uchar *out = pfile->trad_out_cur;
129
130   do
131     {
132       do
133         *out++ = *cur++;
134       while (ISIDNUM (*cur));
135       cur = skip_escaped_newlines (pfile, cur);
136     }
137   while (ISIDNUM (*cur));
138
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,
143                                      len, HT_ALLOC);
144 }
145
146 /* Overlays the true file buffer temporarily with text of length LEN
147    starting at START.  The true buffer is restored upon calling
148    restore_buff().  */
149 void
150 _cpp_overlay_buffer (pfile, start, len)
151      cpp_reader *pfile;
152      const uchar *start;
153      size_t len;
154 {
155   cpp_buffer *buffer = pfile->buffer;
156
157   buffer->saved_cur = buffer->cur;
158   buffer->saved_rlimit = buffer->rlimit;
159   buffer->saved_line_base = buffer->line_base;
160
161   buffer->cur = start;
162   buffer->line_base = start;
163   buffer->rlimit = start + len;
164 }
165
166 /* Restores a buffer overlaid by _cpp_overlay_buffer().  */
167 static void
168 restore_buff (pfile)
169      cpp_reader *pfile;
170 {
171   cpp_buffer *buffer = pfile->buffer;
172
173   buffer->cur = buffer->saved_cur;
174   buffer->rlimit = buffer->saved_rlimit;
175   buffer->line_base = buffer->saved_line_base;
176 }
177
178 /* Reads a logical line into the output buffer.  Returns TRUE if there
179    is more text left in the buffer.  */
180 bool
181 _cpp_read_logical_line_trad (pfile)
182      cpp_reader *pfile;
183 {
184   cpp_buffer *buffer;
185   unsigned int first_line;
186
187   restore_buff (pfile);
188
189   first_line = pfile->line = pfile->trad_line;
190
191   buffer = pfile->buffer;
192   if (buffer->cur == buffer->rlimit)
193     {
194       bool stop = true;
195
196       /* Don't pop the last buffer.  */
197       if (buffer->prev)
198         {
199           stop = buffer->return_at_eof;
200           _cpp_pop_buffer (pfile);
201         }
202
203       if (stop)
204         return false;
205     }
206
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);
213   return true;
214 }
215
216 /* Copies the next logical line in the current buffer to the output
217    buffer.  The output is guaranteed to terminate with a NUL
218    character.  */
219 static void
220 scan_out_logical_line (pfile)
221      cpp_reader *pfile;
222 {
223   cpp_buffer *buffer = pfile->buffer;
224   const uchar *cur = buffer->cur;
225   unsigned int c, quote = 0;
226   uchar *out;
227
228   check_output_buffer (pfile, buffer->rlimit - cur);
229   out = pfile->trad_out_cur;
230
231   for (;;)
232     {
233       c = *cur++;
234       *out++ = c;
235
236       /* There are only a few entities we need to catch: comments,
237          identifiers, newlines, escaped newlines, # and '\0'.  */
238       switch (c)
239         {
240         case '\0':
241           if (cur - 1 != buffer->rlimit)
242             break;
243           cur--;
244           if (!buffer->from_stage3)
245             cpp_error (pfile, DL_PEDWARN, "no newline at end of file");
246           pfile->line++;
247           if (0)
248             {
249             case '\r': case '\n':
250               cur = handle_newline (pfile, cur - 1);
251             }
252           out[-1] = '\n';
253           out[0] = '\0';
254           buffer->cur = cur;
255           pfile->trad_out_cur = out;
256           return;
257
258         case '"':
259         case '\'':
260           if (c == quote)
261             quote = 0;
262           else if (!quote)
263             quote = c;
264           break;
265
266         case '\\':
267           if (is_vspace (*cur))
268             out--, cur = skip_escaped_newlines (pfile, cur - 1);
269           else
270             {
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 == '\'')
275                 *out++ = *cur++;
276             }
277           break;
278
279         case '/':
280           /* Traditional CPP does not recognize comments within
281              literals.  */
282           if (!quote)
283             {
284               cur = skip_escaped_newlines (pfile, cur);
285               if (*cur == '*')
286                 out--, cur = skip_comment (pfile, cur + 1);
287             }
288           break;
289
290         case '_':
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':
295         case 'y': case 'z':
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':
300         case 'Y': case 'Z':
301           {
302             cpp_hashnode *node;
303
304             pfile->trad_out_cur = --out;
305             node = lex_identifier (pfile, cur - 1);
306             out = pfile->trad_out_cur;
307             cur = buffer->cur;
308           }
309           break;
310
311         default:
312           break;
313         }
314     }
315 }