* Makefile.in (cppexp.o): Depend on cpphash.h.
[official-gcc.git] / gcc / c-pragma.c
blobbfb6bdc6efb829cd2bbc91ec26128c518380b6f1
1 /* Handle #pragma, system V.4 style. Supports #pragma weak and #pragma pack.
2 Copyright (C) 1992, 1997, 1998, 1999 Free Software Foundation, Inc.
4 This file is part of GNU CC.
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.
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.
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. */
21 #include "config.h"
22 #include "system.h"
23 #include "rtl.h"
24 #include "tree.h"
25 #include "function.h"
26 #include "defaults.h"
27 #include "c-pragma.h"
28 #include "flags.h"
29 #include "toplev.h"
31 #ifdef HANDLE_GENERIC_PRAGMAS
33 #ifdef HANDLE_PRAGMA_PACK
34 /* When structure field packing is in effect, this variable is the
35 number of bits to use as the maximum alignment. When packing is not
36 in effect, this is zero. */
38 extern int maximum_field_alignment;
39 #endif
42 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
43 typedef struct align_stack
45 int alignment;
46 unsigned int num_pushes;
47 tree id;
48 struct align_stack * prev;
49 } align_stack;
51 static struct align_stack * alignment_stack = NULL;
53 static int push_alignment PROTO((int, tree));
54 static int pop_alignment PROTO((tree));
56 /* Push an alignment value onto the stack. */
57 static int
58 push_alignment (alignment, id)
59 int alignment;
60 tree id;
62 switch (alignment)
64 case 0:
65 case 1:
66 case 2:
67 case 4:
68 case 8:
69 case 16:
70 break;
71 default:
72 warning ("\
73 Alignment must be a small power of two, not %d, in #pragma pack",
74 alignment);
75 return 0;
78 if (alignment_stack == NULL
79 || alignment_stack->alignment != alignment
80 || id != NULL_TREE)
82 align_stack * entry;
84 entry = (align_stack *) xmalloc (sizeof (* entry));
86 if (entry == NULL)
88 warning ("Out of memory pushing #pragma pack");
89 return 0;
92 entry->alignment = alignment;
93 entry->num_pushes = 1;
94 entry->id = id;
95 entry->prev = alignment_stack;
97 alignment_stack = entry;
99 maximum_field_alignment = alignment * 8;
101 else
102 alignment_stack->num_pushes ++;
104 return 1;
107 /* Undo a push of an alignment onto the stack. */
108 static int
109 pop_alignment (id)
110 tree id;
112 align_stack * entry;
114 if (alignment_stack == NULL)
116 warning ("\
117 #pragma pack (pop) encountered without matching #pragma pack (push, <n>)"
119 return 0;
122 /* If we got an identifier, strip away everything above the target
123 entry so that the next step will restore the state just below it. */
124 if (id)
126 for (entry = alignment_stack; entry; entry = entry->prev)
127 if (entry->id == id)
129 entry->num_pushes = 1;
130 alignment_stack = entry;
131 break;
133 if (entry == NULL)
134 warning ("\
135 #pragma pack(pop, %s) encountered without matching #pragma pack(push, %s, <n>)"
136 , IDENTIFIER_POINTER (id), IDENTIFIER_POINTER (id));
139 if (-- alignment_stack->num_pushes == 0)
141 entry = alignment_stack->prev;
143 if (entry == NULL)
144 maximum_field_alignment = 0;
145 else
146 maximum_field_alignment = entry->alignment * 8;
148 free (alignment_stack);
150 alignment_stack = entry;
153 return 1;
156 /* Generate 'packed' and 'aligned' attributes for decls whilst a
157 #pragma pack(push... is in effect. */
158 void
159 insert_pack_attributes (node, attributes, prefix)
160 tree node;
161 tree * attributes;
162 tree * prefix;
164 tree a;
165 int field_alignment;
167 /* If we are not packing, then there is nothing to do. */
168 if (maximum_field_alignment == 0
169 || alignment_stack == NULL)
170 return;
172 /* We are only interested in fields. */
173 if (TREE_CODE_CLASS (TREE_CODE (node)) != 'd'
174 || TREE_CODE (node) != FIELD_DECL)
175 return;
177 field_alignment = TYPE_ALIGN (TREE_TYPE (node));
178 if (field_alignment <= 0 || field_alignment > maximum_field_alignment)
179 field_alignment = maximum_field_alignment;
181 /* Add a 'packed' attribute. */
182 * attributes = tree_cons (get_identifier ("packed"), NULL, * attributes);
184 /* If the alignment is > 8 then add an alignment attribute as well. */
185 if (field_alignment > 8)
187 /* If the aligned attribute is already present then do not override it. */
188 for (a = * attributes; a; a = TREE_CHAIN (a))
190 tree name = TREE_PURPOSE (a);
191 if (strcmp (IDENTIFIER_POINTER (name), "aligned") == 0)
192 break;
195 if (a == NULL)
196 for (a = * prefix; a; a = TREE_CHAIN (a))
198 tree name = TREE_PURPOSE (a);
199 if (strcmp (IDENTIFIER_POINTER (name), "aligned") == 0)
200 break;
203 if (a == NULL)
205 * attributes = tree_cons
206 (get_identifier ("aligned"),
207 tree_cons (NULL,
208 build_int_2 (field_alignment / 8, 0),
209 NULL),
210 * attributes);
214 return;
216 #endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
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.
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. */
232 handle_pragma_token (string, token)
233 const char * string;
234 tree token;
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 static tree id;
243 /* If we have reached the end of the #pragma directive then
244 determine what value we should return. */
246 if (string == NULL)
248 int ret_val = 0;
250 switch (type)
252 default:
253 abort ();
254 break;
256 case ps_done:
257 /* The pragma was not recognised. */
258 break;
260 #ifdef HANDLE_PRAGMA_PACK
261 case ps_pack:
262 if (state == ps_right)
264 maximum_field_alignment = align * 8;
265 ret_val = 1;
267 else
268 warning ("malformed `#pragma pack'");
269 break;
270 #endif /* HANDLE_PRAGMA_PACK */
272 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
273 case ps_push:
274 if (state == ps_right)
275 ret_val = push_alignment (align, id);
276 else
277 warning ("malformed '#pragma pack(push[,id],<n>)'");
278 break;
280 case ps_pop:
281 if (state == ps_right)
282 ret_val = pop_alignment (id);
283 else
284 warning ("malformed '#pragma pack(pop[,id])'");
285 break;
286 #endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
288 #ifdef HANDLE_PRAGMA_WEAK
289 case ps_weak:
290 if (HANDLE_PRAGMA_WEAK)
292 if (state == ps_name)
293 ret_val = add_weak (name, NULL);
294 else if (state == ps_value)
295 ret_val = add_weak (name, value);
296 else
297 warning ("malformed `#pragma weak'");
299 else
300 ret_val = 1; /* Ignore the pragma. */
301 break;
302 #endif /* HANDLE_PRAGMA_WEAK */
304 case ps_poison:
305 ret_val = 1;
306 break;
309 type = state = ps_start;
310 id = NULL_TREE;
312 return ret_val;
315 /* If we have been given a token, but it is not an identifier,
316 or a small constant, then something has gone wrong. */
317 if (token)
319 switch (TREE_CODE (token))
321 case IDENTIFIER_NODE:
322 break;
324 case INTEGER_CST:
325 if (TREE_INT_CST_HIGH (token) != 0)
326 return 0;
327 break;
329 default:
330 return 0;
334 switch (state)
336 case ps_start:
337 type = state = ps_done;
338 #ifdef HANDLE_PRAGMA_PACK
339 if (strcmp (string, "pack") == 0)
340 type = state = ps_pack;
341 #endif
342 #ifdef HANDLE_PRAGMA_WEAK
343 if (strcmp (string, "weak") == 0)
344 type = state = ps_weak;
345 #endif
346 if (strcmp (string, "poison") == 0)
347 type = state = ps_poison;
348 break;
350 #ifdef HANDLE_PRAGMA_WEAK
351 case ps_weak:
352 name = permalloc (strlen (string) + 1);
353 if (name == NULL)
355 warning ("Out of memory parsing #pragma weak");
356 state = ps_bad;
358 else
360 strcpy (name, string);
361 state = ps_name;
363 break;
365 case ps_name:
366 state = (strcmp (string, "=") ? ps_bad : ps_equals);
367 break;
369 case ps_equals:
370 value = permalloc (strlen (string) + 1);
371 if (value == NULL)
373 warning ("Out of memory parsing #pragma weak");
374 state = ps_bad;
376 else
378 strcpy (value, string);
379 state = ps_value;
381 break;
383 case ps_value:
384 state = ps_bad;
385 break;
386 #endif /* HANDLE_PRAGMA_WEAK */
388 #ifdef HANDLE_PRAGMA_PACK
389 case ps_pack:
390 state = (strcmp (string, "(") ? ps_bad : ps_left);
391 break;
393 case ps_left:
395 if (token == NULL_TREE)
397 /* #pragma pack () resets packing rules to their
398 defaults. */
399 if (strcmp (string, ")") == 0)
401 align = 0;
402 state = ps_right;
404 else
405 state = ps_bad;
407 else if (TREE_CODE (token) == INTEGER_CST)
408 goto handle_align;
410 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
411 else if (TREE_CODE (token) == IDENTIFIER_NODE)
413 if (strcmp (string, "push") == 0)
414 type = state = ps_push;
415 else if (strcmp (string, "pop") == 0)
416 type = state = ps_pop;
417 else
418 state = ps_bad;
420 #endif
421 else
422 state = ps_bad;
423 break;
425 handle_align:
426 align = TREE_INT_CST_LOW (token);
427 switch (align)
429 case 1:
430 case 2:
431 case 4:
432 case 8:
433 case 16:
434 state = ps_align;
435 break;
437 default:
438 state = ps_bad;
439 break;
441 break;
443 case ps_align:
444 state = (strcmp (string, ")") ? ps_bad : ps_right);
445 break;
447 case ps_right:
448 state = ps_bad;
449 break;
450 #endif /* HANDLE_PRAGMA_PACK */
452 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
453 case ps_push:
454 state = (strcmp (string, ",") ? ps_bad : ps_pushcomma);
455 break;
457 case ps_pushid:
458 state = (strcmp (string, ",") ? ps_bad : ps_pushcomma2);
459 break;
461 case ps_pushcomma:
462 if (token && TREE_CODE (token) == IDENTIFIER_NODE)
464 id = token;
465 state = ps_pushid;
466 break;
469 /* else fall through */
470 case ps_pushcomma2:
471 if (token && TREE_CODE (token) == INTEGER_CST)
472 goto handle_align;
473 else
474 state = ps_bad;
475 break;
477 case ps_pop:
478 if (strcmp (string, ",") == 0)
479 state = ps_popcomma;
480 else
481 state = (strcmp (string, ")") ? ps_bad : ps_right);
482 break;
484 case ps_popcomma:
485 if (token && TREE_CODE (token) == IDENTIFIER_NODE)
487 id = token;
488 state = ps_align;
490 else
491 state = ps_bad;
492 break;
493 #endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
495 case ps_poison:
496 if (token && TREE_CODE (token) != IDENTIFIER_NODE)
497 state = ps_bad;
498 break;
500 case ps_bad:
501 case ps_done:
502 break;
504 default:
505 abort ();
508 return 1;
510 #endif /* HANDLE_GENERIC_PRAGMAS */