Daily bump.
[official-gcc.git] / gcc / c-pragma.c
blob5aa8d9f2870fc5d08e8f6b1c961a5f178d8049be
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 "except.h"
26 #include "function.h"
27 #include "defaults.h"
28 #include "c-pragma.h"
29 #include "flags.h"
30 #include "toplev.h"
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;
40 #endif
43 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
44 typedef struct align_stack
46 int alignment;
47 unsigned int num_pushes;
48 tree id;
49 struct align_stack * prev;
50 } align_stack;
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. */
58 static int
59 push_alignment (alignment, id)
60 int alignment;
61 tree id;
63 switch (alignment)
65 case 0:
66 case 1:
67 case 2:
68 case 4:
69 case 8:
70 case 16:
71 break;
72 default:
73 warning ("\
74 Alignment must be a small power of two, not %d, in #pragma pack",
75 alignment);
76 return 0;
79 if (alignment_stack == NULL
80 || alignment_stack->alignment != alignment
81 || id != NULL_TREE)
83 align_stack * entry;
85 entry = (align_stack *) xmalloc (sizeof (* entry));
87 if (entry == NULL)
89 warning ("Out of memory pushing #pragma pack");
90 return 0;
93 entry->alignment = alignment;
94 entry->num_pushes = 1;
95 entry->id = id;
96 entry->prev = alignment_stack;
98 alignment_stack = entry;
100 maximum_field_alignment = alignment * 8;
102 else
103 alignment_stack->num_pushes ++;
105 return 1;
108 /* Undo a push of an alignment onto the stack. */
109 static int
110 pop_alignment (id)
111 tree id;
113 align_stack * entry;
115 if (alignment_stack == NULL)
117 warning ("\
118 #pragma pack (pop) encountered without matching #pragma pack (push, <n>)"
120 return 0;
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. */
125 if (id)
127 for (entry = alignment_stack; entry; entry = entry->prev)
128 if (entry->id == id)
130 entry->num_pushes = 1;
131 alignment_stack = entry;
132 break;
134 if (entry == NULL)
135 warning ("\
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)
145 maximum_field_alignment = 0;
146 else
147 maximum_field_alignment = entry->alignment * 8;
149 free (alignment_stack);
151 alignment_stack = entry;
154 return 1;
157 /* Generate 'packed' and 'aligned' attributes for decls whilst a
158 #pragma pack(push... is in effect. */
159 void
160 insert_pack_attributes (node, attributes, prefix)
161 tree node;
162 tree * attributes;
163 tree * prefix;
165 tree a;
166 int field_alignment;
168 /* If we are not packing, then there is nothing to do. */
169 if (maximum_field_alignment == 0
170 || alignment_stack == NULL)
171 return;
173 /* We are only interested in fields. */
174 if (TREE_CODE_CLASS (TREE_CODE (node)) != 'd'
175 || TREE_CODE (node) != FIELD_DECL)
176 return;
178 field_alignment = TYPE_ALIGN (TREE_TYPE (node));
179 if (field_alignment <= 0 || field_alignment > maximum_field_alignment)
180 field_alignment = maximum_field_alignment;
182 /* Add a 'packed' attribute. */
183 * attributes = tree_cons (get_identifier ("packed"), NULL, * attributes);
185 /* If the alignment is > 8 then add an alignment attribute as well. */
186 if (field_alignment > 8)
188 /* If the aligned attribute is already present then do not override it. */
189 for (a = * attributes; a; a = TREE_CHAIN (a))
191 tree name = TREE_PURPOSE (a);
192 if (strcmp (IDENTIFIER_POINTER (name), "aligned") == 0)
193 break;
196 if (a == NULL)
197 for (a = * prefix; a; a = TREE_CHAIN (a))
199 tree name = TREE_PURPOSE (a);
200 if (strcmp (IDENTIFIER_POINTER (name), "aligned") == 0)
201 break;
204 if (a == NULL)
206 * attributes = tree_cons
207 (get_identifier ("aligned"),
208 tree_cons (NULL,
209 build_int_2 (field_alignment / 8, 0),
210 NULL),
211 * attributes);
215 return;
217 #endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
219 /* Handle one token of a pragma directive. TOKEN is the current token, and
220 STRING is its printable form. Some front ends do not support generating
221 tokens, and will only pass in a STRING. Also some front ends will reuse
222 the buffer containing STRING, so it must be copied to a local buffer if
223 it needs to be preserved.
225 If STRING is non-NULL, then the return value will be ignored, and there
226 will be futher calls to handle_pragma_token() in order to handle the rest of
227 the line containing the #pragma directive. If STRING is NULL, the entire
228 line has now been presented to handle_pragma_token() and the return value
229 should be zero if the pragma flawed in some way, or if the pragma was not
230 recognised, and non-zero if it was successfully handled. */
233 handle_pragma_token (string, token)
234 const char * string;
235 tree token;
237 static enum pragma_state state = ps_start;
238 static enum pragma_state type;
239 static char * name;
240 static char * value;
241 static int align;
242 static tree id;
244 /* If we have reached the end of the #pragma directive then
245 determine what value we should return. */
247 if (string == NULL)
249 int ret_val = 0;
251 switch (type)
253 default:
254 abort ();
255 break;
257 case ps_done:
258 /* The pragma was not recognised. */
259 break;
261 #ifdef HANDLE_PRAGMA_PACK
262 case ps_pack:
263 if (state == ps_right)
265 maximum_field_alignment = align * 8;
266 ret_val = 1;
268 else
269 warning ("malformed `#pragma pack'");
270 break;
271 #endif /* HANDLE_PRAGMA_PACK */
273 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
274 case ps_push:
275 if (state == ps_right)
276 ret_val = push_alignment (align, id);
277 else
278 warning ("malformed '#pragma pack(push[,id],<n>)'");
279 break;
281 case ps_pop:
282 if (state == ps_right)
283 ret_val = pop_alignment (id);
284 else
285 warning ("malformed '#pragma pack(pop[,id])'");
286 break;
287 #endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
289 #ifdef HANDLE_PRAGMA_WEAK
290 case ps_weak:
291 if (HANDLE_PRAGMA_WEAK)
293 if (state == ps_name)
294 ret_val = add_weak (name, NULL);
295 else if (state == ps_value)
296 ret_val = add_weak (name, value);
297 else
298 warning ("malformed `#pragma weak'");
300 else
301 ret_val = 1; /* Ignore the pragma. */
302 break;
303 #endif /* HANDLE_PRAGMA_WEAK */
306 type = state = ps_start;
307 id = NULL_TREE;
309 return ret_val;
312 /* If we have been given a token, but it is not an identifier,
313 or a small constant, then something has gone wrong. */
314 if (token)
316 switch (TREE_CODE (token))
318 case IDENTIFIER_NODE:
319 break;
321 case INTEGER_CST:
322 if (TREE_INT_CST_HIGH (token) != 0)
323 return 0;
324 break;
326 default:
327 return 0;
331 switch (state)
333 case ps_start:
334 type = state = ps_done;
335 #ifdef HANDLE_PRAGMA_PACK
336 if (strcmp (string, "pack") == 0)
337 type = state = ps_pack;
338 #endif
339 #ifdef HANDLE_PRAGMA_WEAK
340 if (strcmp (string, "weak") == 0)
341 type = state = ps_weak;
342 #endif
343 break;
345 #ifdef HANDLE_PRAGMA_WEAK
346 case ps_weak:
347 name = permalloc (strlen (string) + 1);
348 if (name == NULL)
350 warning ("Out of memory parsing #pragma weak");
351 state = ps_bad;
353 else
355 strcpy (name, string);
356 state = ps_name;
358 break;
360 case ps_name:
361 state = (strcmp (string, "=") ? ps_bad : ps_equals);
362 break;
364 case ps_equals:
365 value = permalloc (strlen (string) + 1);
366 if (value == NULL)
368 warning ("Out of memory parsing #pragma weak");
369 state = ps_bad;
371 else
373 strcpy (value, string);
374 state = ps_value;
376 break;
378 case ps_value:
379 state = ps_bad;
380 break;
381 #endif /* HANDLE_PRAGMA_WEAK */
383 #ifdef HANDLE_PRAGMA_PACK
384 case ps_pack:
385 state = (strcmp (string, "(") ? ps_bad : ps_left);
386 break;
388 case ps_left:
390 if (token == NULL_TREE)
392 /* #pragma pack () resets packing rules to their
393 defaults. */
394 if (strcmp (string, ")") == 0)
396 align = 0;
397 state = ps_right;
399 else
400 state = ps_bad;
402 else if (TREE_CODE (token) == INTEGER_CST)
403 goto handle_align;
405 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
406 else if (TREE_CODE (token) == IDENTIFIER_NODE)
408 if (strcmp (string, "push") == 0)
409 type = state = ps_push;
410 else if (strcmp (string, "pop") == 0)
411 type = state = ps_pop;
412 else
413 state = ps_bad;
415 #endif
416 else
417 state = ps_bad;
418 break;
420 handle_align:
421 align = TREE_INT_CST_LOW (token);
422 switch (align)
424 case 1:
425 case 2:
426 case 4:
427 case 8:
428 case 16:
429 state = ps_align;
430 break;
432 default:
433 state = ps_bad;
434 break;
436 break;
438 case ps_align:
439 state = (strcmp (string, ")") ? ps_bad : ps_right);
440 break;
442 case ps_right:
443 state = ps_bad;
444 break;
445 #endif /* HANDLE_PRAGMA_PACK */
447 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
448 case ps_push:
449 state = (strcmp (string, ",") ? ps_bad : ps_pushcomma);
450 break;
452 case ps_pushid:
453 state = (strcmp (string, ",") ? ps_bad : ps_pushcomma2);
454 break;
456 case ps_pushcomma:
457 if (token && TREE_CODE (token) == IDENTIFIER_NODE)
459 id = token;
460 state = ps_pushid;
461 break;
464 /* else fall through */
465 case ps_pushcomma2:
466 if (token && TREE_CODE (token) == INTEGER_CST)
467 goto handle_align;
468 else
469 state = ps_bad;
470 break;
472 case ps_pop:
473 if (strcmp (string, ",") == 0)
474 state = ps_popcomma;
475 else
476 state = (strcmp (string, ")") ? ps_bad : ps_right);
477 break;
479 case ps_popcomma:
480 if (token && TREE_CODE (token) == IDENTIFIER_NODE)
482 id = token;
483 state = ps_align;
485 else
486 state = ps_bad;
487 break;
488 #endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
490 case ps_bad:
491 case ps_done:
492 break;
494 default:
495 abort ();
498 return 1;
500 #endif /* HANDLE_GENERIC_PRAGMAS */