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;
243 /* If we have reached the end of the #pragma directive then
244 determine what value we should return. */
257 /* The pragma was not recognised. */
260 #ifdef HANDLE_PRAGMA_PACK
262 if (state == ps_right)
264 maximum_field_alignment = align * 8;
268 warning ("malformed `#pragma pack'");
270 #endif /* HANDLE_PRAGMA_PACK */
272 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
274 if (state == ps_right)
275 ret_val = push_alignment (align, id);
277 warning ("malformed '#pragma pack(push[,id],<n>)'");
281 if (state == ps_right)
282 ret_val = pop_alignment (id);
284 warning ("malformed '#pragma pack(pop[,id])'");
286 #endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
288 #ifdef HANDLE_PRAGMA_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);
297 warning ("malformed `#pragma weak'");
300 ret_val = 1; /* Ignore the pragma. */
302 #endif /* HANDLE_PRAGMA_WEAK */
309 type = state = ps_start;
315 /* If we have been given a token, but it is not an identifier,
316 or a small constant, then something has gone wrong. */
319 switch (TREE_CODE (token))
321 case IDENTIFIER_NODE:
325 if (TREE_INT_CST_HIGH (token) != 0)
337 type = state = ps_done;
338 #ifdef HANDLE_PRAGMA_PACK
339 if (strcmp (string, "pack") == 0)
340 type = state = ps_pack;
342 #ifdef HANDLE_PRAGMA_WEAK
343 if (strcmp (string, "weak") == 0)
344 type = state = ps_weak;
346 if (strcmp (string, "poison") == 0)
347 type = state = ps_poison;
350 #ifdef HANDLE_PRAGMA_WEAK
352 name = permalloc (strlen (string) + 1);
355 warning ("Out of memory parsing #pragma weak");
360 strcpy (name, string);
366 state = (strcmp (string, "=") ? ps_bad : ps_equals);
370 value = permalloc (strlen (string) + 1);
373 warning ("Out of memory parsing #pragma weak");
378 strcpy (value, string);
386 #endif /* HANDLE_PRAGMA_WEAK */
388 #ifdef HANDLE_PRAGMA_PACK
390 state = (strcmp (string, "(") ? ps_bad : ps_left);
395 if (token == NULL_TREE)
397 /* #pragma pack () resets packing rules to their
399 if (strcmp (string, ")") == 0)
407 else if (TREE_CODE (token) == INTEGER_CST)
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;
426 align = TREE_INT_CST_LOW (token);
444 state = (strcmp (string, ")") ? ps_bad : ps_right);
450 #endif /* HANDLE_PRAGMA_PACK */
452 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
454 state = (strcmp (string, ",") ? ps_bad : ps_pushcomma);
458 state = (strcmp (string, ",") ? ps_bad : ps_pushcomma2);
462 if (token && TREE_CODE (token) == IDENTIFIER_NODE)
469 /* else fall through */
471 if (token && TREE_CODE (token) == INTEGER_CST)
478 if (strcmp (string, ",") == 0)
481 state = (strcmp (string, ")") ? ps_bad : ps_right);
485 if (token && TREE_CODE (token) == IDENTIFIER_NODE)
493 #endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
496 if (token && TREE_CODE (token) != IDENTIFIER_NODE)
510 #endif /* HANDLE_GENERIC_PRAGMAS */