]> gcc.gnu.org Git - gcc.git/blob - gcc/c-pragma.c
cpplib.c (macroexpand): Correct off-by-one error in handling of escapes.
[gcc.git] / gcc / c-pragma.c
1 /* Handle #pragma, system V.4 style. Supports #pragma weak and #pragma pack.
2 Copyright (C) 1992, 1997, 1998 Free Software Foundation, Inc.
3
4 This file is part of GNU CC.
5
6 GNU CC is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU CC is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU CC; see the file COPYING. If not, write to
18 the Free Software Foundation, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
20
21 #include "config.h"
22 #include "system.h"
23 #include "rtl.h"
24 #include "tree.h"
25 #include "except.h"
26 #include "function.h"
27 #include "defaults.h"
28 #include "c-pragma.h"
29 #include "flags.h"
30 #include "toplev.h"
31
32 #ifdef HANDLE_GENERIC_PRAGMAS
33
34 #ifdef HANDLE_PRAGMA_PACK
35 /* When structure field packing is in effect, this variable is the
36 number of bits to use as the maximum alignment. When packing is not
37 in effect, this is zero. */
38
39 extern int maximum_field_alignment;
40 #endif
41
42
43 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
44 typedef struct align_stack
45 {
46 int alignment;
47 unsigned int num_pushes;
48 struct align_stack * prev;
49 } align_stack;
50
51 static struct align_stack * alignment_stack = NULL;
52
53 static int push_alignment PROTO((int));
54 static int pop_alignment PROTO((void));
55
56 /* Push an alignment value onto the stack. */
57 static int
58 push_alignment (alignment)
59 int alignment;
60 {
61 switch (alignment)
62 {
63 case 0:
64 case 1:
65 case 2:
66 case 4:
67 case 8:
68 case 16:
69 break;
70 default:
71 warning ("\
72 Alignment must be a small power of two, not %d, in #pragma pack",
73 alignment);
74 return 0;
75 }
76
77 if (alignment_stack == NULL
78 || alignment_stack->alignment != alignment)
79 {
80 align_stack * entry;
81
82 entry = (align_stack *) xmalloc (sizeof (* entry));
83
84 if (entry == NULL)
85 {
86 warning ("Out of memory pushing #pragma pack");
87 return 0;
88 }
89
90 entry->alignment = alignment;
91 entry->num_pushes = 1;
92 entry->prev = alignment_stack;
93
94 alignment_stack = entry;
95
96 if (alignment < 8)
97 maximum_field_alignment = alignment * 8;
98 else
99 /* MSVC ignores alignments > 4. */
100 maximum_field_alignment = 0;
101 }
102 else
103 alignment_stack->num_pushes ++;
104
105 return 1;
106 }
107
108 /* Undo a push of an alignment onto the stack. */
109 static int
110 pop_alignment ()
111 {
112 if (alignment_stack == NULL)
113 {
114 warning ("\
115 #pragma pack(pop) encountered without corresponding #pragma pack(push,<n>)");
116 return 0;
117 }
118
119 if (-- alignment_stack->num_pushes == 0)
120 {
121 align_stack * entry;
122
123 entry = alignment_stack->prev;
124
125 if (entry == NULL || entry->alignment > 4)
126 maximum_field_alignment = 0;
127 else
128 maximum_field_alignment = entry->alignment * 8;
129
130 free (alignment_stack);
131
132 alignment_stack = entry;
133 }
134
135 return 1;
136 }
137
138 /* Generate 'packed' and 'aligned' attributes for decls whilst a
139 #pragma pack(push... is in effect. */
140 void
141 insert_pack_attributes (node, attributes, prefix)
142 tree node;
143 tree * attributes;
144 tree * prefix;
145 {
146 tree a;
147
148 /* If we are not packing, then there is nothing to do. */
149 if (maximum_field_alignment == 0)
150 return;
151
152 /* We are only interested in fields. */
153 if (TREE_CODE_CLASS (TREE_CODE (node)) != 'd'
154 || TREE_CODE (node) != FIELD_DECL)
155 return;
156
157 /* Add a 'packed' attribute. */
158 * attributes = tree_cons (get_identifier ("packed"), NULL, * attributes);
159
160 /* If the alignment is > 8 then add an alignment attribute as well. */
161 if (maximum_field_alignment > 8)
162 {
163 /* If the aligned attribute is already present then do not override it. */
164 for (a = * attributes; a; a = TREE_CHAIN (a))
165 {
166 tree name = TREE_PURPOSE (a);
167 if (strcmp (IDENTIFIER_POINTER (name), "aligned") == 0)
168 break;
169 }
170
171 if (a == NULL)
172 for (a = * prefix; a; a = TREE_CHAIN (a))
173 {
174 tree name = TREE_PURPOSE (a);
175 if (strcmp (IDENTIFIER_POINTER (name), "aligned") == 0)
176 break;
177 }
178
179 if (a == NULL)
180 {
181 * attributes = tree_cons
182 (get_identifier ("aligned"),
183 tree_cons (NULL,
184 build_int_2 (maximum_field_alignment / 8, 0),
185 NULL),
186 * attributes);
187 }
188 }
189
190 return;
191 }
192 #endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
193 \f
194 #ifdef HANDLE_PRAGMA_WEAK
195 static int add_weak PROTO((char *, char *));
196
197 static int
198 add_weak (name, value)
199 char * name;
200 char * value;
201 {
202 struct weak_syms * weak;
203
204 weak = (struct weak_syms *) permalloc (sizeof (struct weak_syms));
205
206 if (weak == NULL)
207 return 0;
208
209 weak->next = weak_decls;
210 weak->name = name;
211 weak->value = value;
212 weak_decls = weak;
213
214 return 1;
215 }
216 #endif /* HANDLE_PRAGMA_WEAK */
217 \f
218 /* Handle one token of a pragma directive. TOKEN is the current token, and
219 STRING is its printable form. Some front ends do not support generating
220 tokens, and will only pass in a STRING. Also some front ends will reuse
221 the buffer containing STRING, so it must be copied to a local buffer if
222 it needs to be preserved.
223
224 If STRING is non-NULL, then the return value will be ignored, and there
225 will be futher calls to handle_pragma_token() in order to handle the rest of
226 the line containing the #pragma directive. If STRING is NULL, the entire
227 line has now been presented to handle_pragma_token() and the return value
228 should be zero if the pragma flawed in some way, or if the pragma was not
229 recognised, and non-zero if it was successfully handled. */
230
231 int
232 handle_pragma_token (string, token)
233 char * string;
234 tree token;
235 {
236 static enum pragma_state state = ps_start;
237 static enum pragma_state type;
238 static char * name;
239 static char * value;
240 static int align;
241
242 /* If we have reached the end of the #pragma directive then
243 determine what value we should return. */
244
245 if (string == NULL)
246 {
247 int ret_val = 0;
248
249 switch (type)
250 {
251 default:
252 abort ();
253 break;
254
255 case ps_done:
256 /* The pragma was not recognised. */
257 break;
258
259 #ifdef HANDLE_PRAGMA_PACK
260 case ps_pack:
261 if (state == ps_right)
262 {
263 maximum_field_alignment = align * 8;
264 ret_val = 1;
265 }
266 else
267 warning ("malformed `#pragma pack'");
268 break;
269 #endif /* HANDLE_PRAGMA_PACK */
270
271 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
272 case ps_push:
273 if (state == ps_right)
274 ret_val = push_alignment (align);
275 else
276 warning ("incomplete '#pragma pack(push,<n>)'");
277 break;
278
279 case ps_pop:
280 if (state == ps_right)
281 ret_val = pop_alignment ();
282 else
283 warning ("missing closing parenthesis in '#pragma pack(pop)'");
284 break;
285 #endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
286
287 #ifdef HANDLE_PRAGMA_WEAK
288 case ps_weak:
289 if (HANDLE_PRAGMA_WEAK)
290 {
291 if (state == ps_name)
292 ret_val = add_weak (name, NULL);
293 else if (state == ps_value)
294 ret_val = add_weak (name, value);
295 else
296 warning ("malformed `#pragma weak'");
297 }
298 else
299 ret_val = 1; /* Ignore the pragma. */
300 break;
301 #endif /* HANDLE_PRAGMA_WEAK */
302 }
303
304 type = state = ps_start;
305
306 return ret_val;
307 }
308
309 /* If we have been given a token, but it is not an identifier,
310 or a small constant, then something has gone wrong. */
311 if (token)
312 {
313 switch (TREE_CODE (token))
314 {
315 case IDENTIFIER_NODE:
316 break;
317
318 case INTEGER_CST:
319 if (TREE_INT_CST_HIGH (token) != 0)
320 return 0;
321 break;
322
323 default:
324 return 0;
325 }
326 }
327
328 switch (state)
329 {
330 case ps_start:
331 type = state = ps_done;
332 #ifdef HANDLE_PRAGMA_PACK
333 if (strcmp (string, "pack") == 0)
334 type = state = ps_pack;
335 #endif
336 #ifdef HANDLE_PRAGMA_WEAK
337 if (strcmp (string, "weak") == 0)
338 type = state = ps_weak;
339 #endif
340 break;
341
342 #ifdef HANDLE_PRAGMA_WEAK
343 case ps_weak:
344 name = permalloc (strlen (string) + 1);
345 if (name == NULL)
346 {
347 warning ("Out of memory parsing #pragma weak");
348 state = ps_bad;
349 }
350 else
351 {
352 strcpy (name, string);
353 state = ps_name;
354 }
355 break;
356
357 case ps_name:
358 state = (strcmp (string, "=") ? ps_bad : ps_equals);
359 break;
360
361 case ps_equals:
362 value = permalloc (strlen (string) + 1);
363 if (value == NULL)
364 {
365 warning ("Out of memory parsing #pragma weak");
366 state = ps_bad;
367 }
368 else
369 {
370 strcpy (value, string);
371 state = ps_value;
372 }
373 break;
374
375 case ps_value:
376 state = ps_bad;
377 break;
378 #endif /* HANDLE_PRAGMA_WEAK */
379
380 #ifdef HANDLE_PRAGMA_PACK
381 case ps_pack:
382 state = (strcmp (string, "(") ? ps_bad : ps_left);
383 break;
384
385 case ps_left:
386 align = atoi (string);
387 switch (align)
388 {
389 case 1:
390 case 2:
391 case 4:
392 state = ps_align;
393 break;
394
395 case 0:
396 state = (strcmp (string, ")") ? ps_bad : ps_right);
397 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
398 if (state == ps_bad)
399 {
400 if (strcmp (string, "push") == 0)
401 type = state = ps_push;
402 else if (strcmp (string, "pop") == 0)
403 type = state = ps_pop;
404 }
405 #endif
406 break;
407
408 default:
409 state = ps_bad;
410 break;
411 }
412 break;
413
414 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
415 case ps_pop:
416 #endif
417 case ps_align:
418 state = (strcmp (string, ")") ? ps_bad : ps_right);
419 break;
420
421 case ps_right:
422 state = ps_bad;
423 break;
424 #endif /* HANDLE_PRAGMA_PACK */
425
426 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
427 case ps_push:
428 state = (strcmp (string, ",") ? ps_bad : ps_comma);
429 break;
430
431 case ps_comma:
432 align = atoi (string);
433 state = ps_align;
434 break;
435 #endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
436
437 case ps_bad:
438 case ps_done:
439 break;
440
441 default:
442 abort ();
443 }
444
445 return 1;
446 }
447 #endif /* HANDLE_GENERIC_PRAGMAS */
This page took 0.054229 seconds and 5 git commands to generate.