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)
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. */
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
;
42 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
43 typedef struct align_stack
46 unsigned int num_pushes
;
48 struct align_stack
* prev
;
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. */
58 push_alignment (alignment
, id
)
73 Alignment must be a small power of two, not %d, in #pragma pack",
78 if (alignment_stack
== NULL
79 || alignment_stack
->alignment
!= alignment
84 entry
= (align_stack
*) xmalloc (sizeof (* entry
));
88 warning ("Out of memory pushing #pragma pack");
92 entry
->alignment
= alignment
;
93 entry
->num_pushes
= 1;
95 entry
->prev
= alignment_stack
;
97 alignment_stack
= entry
;
99 maximum_field_alignment
= alignment
* 8;
102 alignment_stack
->num_pushes
++;
107 /* Undo a push of an alignment onto the stack. */
114 if (alignment_stack
== NULL
)
117 #pragma pack (pop) encountered without matching #pragma pack (push, <n>)"
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. */
126 for (entry
= alignment_stack
; entry
; entry
= entry
->prev
)
129 entry
->num_pushes
= 1;
130 alignment_stack
= entry
;
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
;
144 maximum_field_alignment
= 0;
146 maximum_field_alignment
= entry
->alignment
* 8;
148 free (alignment_stack
);
150 alignment_stack
= entry
;
156 /* Generate 'packed' and 'aligned' attributes for decls whilst a
157 #pragma pack(push... is in effect. */
159 insert_pack_attributes (node
, attributes
, prefix
)
167 /* If we are not packing, then there is nothing to do. */
168 if (maximum_field_alignment
== 0
169 || alignment_stack
== NULL
)
172 /* We are only interested in fields. */
173 if (TREE_CODE_CLASS (TREE_CODE (node
)) != 'd'
174 || TREE_CODE (node
) != FIELD_DECL
)
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)
196 for (a
= * prefix
; a
; a
= TREE_CHAIN (a
))
198 tree name
= TREE_PURPOSE (a
);
199 if (strcmp (IDENTIFIER_POINTER (name
), "aligned") == 0)
205 * attributes
= tree_cons
206 (get_identifier ("aligned"),
208 build_int_2 (field_alignment
/ 8, 0),
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
)
236 static enum pragma_state state
= ps_start
;
237 static enum pragma_state type
;
238 #ifdef HANDLE_PRAGMA_WEAK
242 #if defined(HANDLE_PRAGMA_PACK) || defined(HANDLE_PRAGMA_PACK_PUSH_POP)
247 /* If we have reached the end of the #pragma directive then
248 determine what value we should return. */
261 /* The pragma was not recognised. */
264 #ifdef HANDLE_PRAGMA_PACK
266 if (state
== ps_right
)
268 maximum_field_alignment
= align
* 8;
272 warning ("malformed `#pragma pack'");
274 #endif /* HANDLE_PRAGMA_PACK */
276 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
278 if (state
== ps_right
)
279 ret_val
= push_alignment (align
, id
);
281 warning ("malformed '#pragma pack(push[,id],<n>)'");
285 if (state
== ps_right
)
286 ret_val
= pop_alignment (id
);
288 warning ("malformed '#pragma pack(pop[,id])'");
290 #endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
292 #ifdef HANDLE_PRAGMA_WEAK
294 if (HANDLE_PRAGMA_WEAK
)
296 if (state
== ps_name
)
297 ret_val
= add_weak (name
, NULL
);
298 else if (state
== ps_value
)
299 ret_val
= add_weak (name
, value
);
301 warning ("malformed `#pragma weak'");
304 ret_val
= 1; /* Ignore the pragma. */
306 #endif /* HANDLE_PRAGMA_WEAK */
313 type
= state
= ps_start
;
319 /* If we have been given a token, but it is not an identifier,
320 or a small constant, then something has gone wrong. */
323 switch (TREE_CODE (token
))
325 case IDENTIFIER_NODE
:
329 if (TREE_INT_CST_HIGH (token
) != 0)
341 type
= state
= ps_done
;
342 #ifdef HANDLE_PRAGMA_PACK
343 if (strcmp (string
, "pack") == 0)
344 type
= state
= ps_pack
;
346 #ifdef HANDLE_PRAGMA_WEAK
347 if (strcmp (string
, "weak") == 0)
348 type
= state
= ps_weak
;
350 if (strcmp (string
, "poison") == 0)
351 type
= state
= ps_poison
;
354 #ifdef HANDLE_PRAGMA_WEAK
356 name
= permalloc (strlen (string
) + 1);
359 warning ("Out of memory parsing #pragma weak");
364 strcpy (name
, string
);
370 state
= (strcmp (string
, "=") ? ps_bad
: ps_equals
);
374 value
= permalloc (strlen (string
) + 1);
377 warning ("Out of memory parsing #pragma weak");
382 strcpy (value
, string
);
390 #endif /* HANDLE_PRAGMA_WEAK */
392 #ifdef HANDLE_PRAGMA_PACK
394 state
= (strcmp (string
, "(") ? ps_bad
: ps_left
);
399 if (token
== NULL_TREE
)
401 /* #pragma pack () resets packing rules to their
403 if (strcmp (string
, ")") == 0)
411 else if (TREE_CODE (token
) == INTEGER_CST
)
414 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
415 else if (TREE_CODE (token
) == IDENTIFIER_NODE
)
417 if (strcmp (string
, "push") == 0)
418 type
= state
= ps_push
;
419 else if (strcmp (string
, "pop") == 0)
420 type
= state
= ps_pop
;
430 align
= TREE_INT_CST_LOW (token
);
448 state
= (strcmp (string
, ")") ? ps_bad
: ps_right
);
454 #endif /* HANDLE_PRAGMA_PACK */
456 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
458 state
= (strcmp (string
, ",") ? ps_bad
: ps_pushcomma
);
462 state
= (strcmp (string
, ",") ? ps_bad
: ps_pushcomma2
);
466 if (token
&& TREE_CODE (token
) == IDENTIFIER_NODE
)
473 /* else fall through */
475 if (token
&& TREE_CODE (token
) == INTEGER_CST
)
482 if (strcmp (string
, ",") == 0)
485 state
= (strcmp (string
, ")") ? ps_bad
: ps_right
);
489 if (token
&& TREE_CODE (token
) == IDENTIFIER_NODE
)
497 #endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
500 if (token
&& TREE_CODE (token
) != IDENTIFIER_NODE
)
514 #endif /* HANDLE_GENERIC_PRAGMAS */