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. */
32 #ifdef HANDLE_GENERIC_PRAGMAS
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. */
39 extern int maximum_field_alignment
;
43 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
44 typedef struct align_stack
47 unsigned int num_pushes
;
49 struct align_stack
* prev
;
52 static struct align_stack
* alignment_stack
= NULL
;
54 static int push_alignment
PROTO((int, tree
));
55 static int pop_alignment
PROTO((tree
));
57 /* Push an alignment value onto the stack. */
59 push_alignment (alignment
, id
)
74 Alignment must be a small power of two, not %d, in #pragma pack",
79 if (alignment_stack
== NULL
80 || alignment_stack
->alignment
!= alignment
85 entry
= (align_stack
*) xmalloc (sizeof (* entry
));
89 warning ("Out of memory pushing #pragma pack");
93 entry
->alignment
= alignment
;
94 entry
->num_pushes
= 1;
96 entry
->prev
= alignment_stack
;
98 alignment_stack
= entry
;
100 maximum_field_alignment
= alignment
* 8;
103 alignment_stack
->num_pushes
++;
108 /* Undo a push of an alignment onto the stack. */
115 if (alignment_stack
== NULL
)
118 #pragma pack (pop) encountered without matching #pragma pack (push, <n>)"
123 /* If we got an identifier, strip away everything above the target
124 entry so that the next step will restore the state just below it. */
127 for (entry
= alignment_stack
; entry
; entry
= entry
->prev
)
130 entry
->num_pushes
= 1;
131 alignment_stack
= entry
;
136 #pragma pack(pop, %s) encountered without matching #pragma pack(push, %s, <n>)"
137 , IDENTIFIER_POINTER (id
), IDENTIFIER_POINTER (id
));
140 if (-- alignment_stack
->num_pushes
== 0)
142 entry
= alignment_stack
->prev
;
144 if (entry
== NULL
|| entry
->alignment
> 4)
145 maximum_field_alignment
= 0;
147 maximum_field_alignment
= entry
->alignment
* 8;
149 free (alignment_stack
);
151 alignment_stack
= entry
;
157 /* Generate 'packed' and 'aligned' attributes for decls whilst a
158 #pragma pack(push... is in effect. */
160 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 /* Add a 'packed' attribute. */
178 * attributes
= tree_cons (get_identifier ("packed"), NULL
, * attributes
);
180 /* If the alignment is > 8 then add an alignment attribute as well. */
181 if (maximum_field_alignment
> 8)
183 /* If the aligned attribute is already present then do not override it. */
184 for (a
= * attributes
; a
; a
= TREE_CHAIN (a
))
186 tree name
= TREE_PURPOSE (a
);
187 if (strcmp (IDENTIFIER_POINTER (name
), "aligned") == 0)
192 for (a
= * prefix
; a
; a
= TREE_CHAIN (a
))
194 tree name
= TREE_PURPOSE (a
);
195 if (strcmp (IDENTIFIER_POINTER (name
), "aligned") == 0)
201 * attributes
= tree_cons
202 (get_identifier ("aligned"),
204 build_int_2 (maximum_field_alignment
/ 8, 0),
212 #endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
214 /* Handle one token of a pragma directive. TOKEN is the current token, and
215 STRING is its printable form. Some front ends do not support generating
216 tokens, and will only pass in a STRING. Also some front ends will reuse
217 the buffer containing STRING, so it must be copied to a local buffer if
218 it needs to be preserved.
220 If STRING is non-NULL, then the return value will be ignored, and there
221 will be futher calls to handle_pragma_token() in order to handle the rest of
222 the line containing the #pragma directive. If STRING is NULL, the entire
223 line has now been presented to handle_pragma_token() and the return value
224 should be zero if the pragma flawed in some way, or if the pragma was not
225 recognised, and non-zero if it was successfully handled. */
228 handle_pragma_token (string
, token
)
232 static enum pragma_state state
= ps_start
;
233 static enum pragma_state type
;
239 /* If we have reached the end of the #pragma directive then
240 determine what value we should return. */
253 /* The pragma was not recognised. */
256 #ifdef HANDLE_PRAGMA_PACK
258 if (state
== ps_right
)
260 maximum_field_alignment
= align
* 8;
264 warning ("malformed `#pragma pack'");
266 #endif /* HANDLE_PRAGMA_PACK */
268 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
270 if (state
== ps_right
)
271 ret_val
= push_alignment (align
, id
);
273 warning ("malformed '#pragma pack(push[,id],<n>)'");
277 if (state
== ps_right
)
278 ret_val
= pop_alignment (id
);
280 warning ("malformed '#pragma pack(pop[,id])'");
282 #endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
284 #ifdef HANDLE_PRAGMA_WEAK
286 if (HANDLE_PRAGMA_WEAK
)
288 if (state
== ps_name
)
289 ret_val
= add_weak (name
, NULL
);
290 else if (state
== ps_value
)
291 ret_val
= add_weak (name
, value
);
293 warning ("malformed `#pragma weak'");
296 ret_val
= 1; /* Ignore the pragma. */
298 #endif /* HANDLE_PRAGMA_WEAK */
301 type
= state
= ps_start
;
307 /* If we have been given a token, but it is not an identifier,
308 or a small constant, then something has gone wrong. */
311 switch (TREE_CODE (token
))
313 case IDENTIFIER_NODE
:
317 if (TREE_INT_CST_HIGH (token
) != 0)
329 type
= state
= ps_done
;
330 #ifdef HANDLE_PRAGMA_PACK
331 if (strcmp (string
, "pack") == 0)
332 type
= state
= ps_pack
;
334 #ifdef HANDLE_PRAGMA_WEAK
335 if (strcmp (string
, "weak") == 0)
336 type
= state
= ps_weak
;
340 #ifdef HANDLE_PRAGMA_WEAK
342 name
= permalloc (strlen (string
) + 1);
345 warning ("Out of memory parsing #pragma weak");
350 strcpy (name
, string
);
356 state
= (strcmp (string
, "=") ? ps_bad
: ps_equals
);
360 value
= permalloc (strlen (string
) + 1);
363 warning ("Out of memory parsing #pragma weak");
368 strcpy (value
, string
);
376 #endif /* HANDLE_PRAGMA_WEAK */
378 #ifdef HANDLE_PRAGMA_PACK
380 state
= (strcmp (string
, "(") ? ps_bad
: ps_left
);
385 if (token
== NULL_TREE
)
387 /* #pragma pack () resets packing rules to their
389 if (strcmp (string
, ")") == 0)
397 else if (TREE_CODE (token
) == INTEGER_CST
)
400 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
401 else if (TREE_CODE (token
) == IDENTIFIER_NODE
)
403 if (strcmp (string
, "push") == 0)
404 type
= state
= ps_push
;
405 else if (strcmp (string
, "pop") == 0)
406 type
= state
= ps_pop
;
416 align
= TREE_INT_CST_LOW (token
);
434 state
= (strcmp (string
, ")") ? ps_bad
: ps_right
);
440 #endif /* HANDLE_PRAGMA_PACK */
442 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
444 state
= (strcmp (string
, ",") ? ps_bad
: ps_pushcomma
);
448 state
= (strcmp (string
, ",") ? ps_bad
: ps_pushcomma2
);
452 if (token
&& TREE_CODE (token
) == IDENTIFIER_NODE
)
459 /* else fall through */
461 if (token
&& TREE_CODE (token
) == INTEGER_CST
)
468 if (strcmp (string
, ",") == 0)
471 state
= (strcmp (string
, ")") ? ps_bad
: ps_right
);
475 if (token
&& TREE_CODE (token
) == IDENTIFIER_NODE
)
483 #endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
495 #endif /* HANDLE_GENERIC_PRAGMAS */