[official-gcc.git] / gcc / c-pragma.c
blobde9cfb899e5590036c792ffdf2833c38083e1efd
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 || entry->alignment > 4)
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;
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 /* 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)
188 break;
191 if (a == NULL)
192 for (a = * prefix; a; a = TREE_CHAIN (a))
194 tree name = TREE_PURPOSE (a);
195 if (strcmp (IDENTIFIER_POINTER (name), "aligned") == 0)
196 break;
199 if (a == NULL)
201 * attributes = tree_cons
202 (get_identifier ("aligned"),
203 tree_cons (NULL,
204 build_int_2 (maximum_field_alignment / 8, 0),
205 NULL),
206 * attributes);
210 return;
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)
229 const char * string;
230 tree token;
232 static enum pragma_state state = ps_start;
233 static enum pragma_state type;
234 static char * name;
235 static char * value;
236 static int align;
237 static tree id;
239 /* If we have reached the end of the #pragma directive then
240 determine what value we should return. */
242 if (string == NULL)
244 int ret_val = 0;
246 switch (type)
248 default:
249 abort ();
250 break;
252 case ps_done:
253 /* The pragma was not recognised. */
254 break;
256 #ifdef HANDLE_PRAGMA_PACK
257 case ps_pack:
258 if (state == ps_right)
260 maximum_field_alignment = align * 8;
261 ret_val = 1;
263 else
264 warning ("malformed `#pragma pack'");
265 break;
266 #endif /* HANDLE_PRAGMA_PACK */
268 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
269 case ps_push:
270 if (state == ps_right)
271 ret_val = push_alignment (align, id);
272 else
273 warning ("malformed '#pragma pack(push[,id],<n>)'");
274 break;
276 case ps_pop:
277 if (state == ps_right)
278 ret_val = pop_alignment (id);
279 else
280 warning ("malformed '#pragma pack(pop[,id])'");
281 break;
282 #endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
284 #ifdef HANDLE_PRAGMA_WEAK
285 case ps_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);
292 else
293 warning ("malformed `#pragma weak'");
295 else
296 ret_val = 1; /* Ignore the pragma. */
297 break;
298 #endif /* HANDLE_PRAGMA_WEAK */
301 type = state = ps_start;
302 id = NULL_TREE;
304 return ret_val;
307 /* If we have been given a token, but it is not an identifier,
308 or a small constant, then something has gone wrong. */
309 if (token)
311 switch (TREE_CODE (token))
313 case IDENTIFIER_NODE:
314 break;
316 case INTEGER_CST:
317 if (TREE_INT_CST_HIGH (token) != 0)
318 return 0;
319 break;
321 default:
322 return 0;
326 switch (state)
328 case ps_start:
329 type = state = ps_done;
330 #ifdef HANDLE_PRAGMA_PACK
331 if (strcmp (string, "pack") == 0)
332 type = state = ps_pack;
333 #endif
334 #ifdef HANDLE_PRAGMA_WEAK
335 if (strcmp (string, "weak") == 0)
336 type = state = ps_weak;
337 #endif
338 break;
340 #ifdef HANDLE_PRAGMA_WEAK
341 case ps_weak:
342 name = permalloc (strlen (string) + 1);
343 if (name == NULL)
345 warning ("Out of memory parsing #pragma weak");
346 state = ps_bad;
348 else
350 strcpy (name, string);
351 state = ps_name;
353 break;
355 case ps_name:
356 state = (strcmp (string, "=") ? ps_bad : ps_equals);
357 break;
359 case ps_equals:
360 value = permalloc (strlen (string) + 1);
361 if (value == NULL)
363 warning ("Out of memory parsing #pragma weak");
364 state = ps_bad;
366 else
368 strcpy (value, string);
369 state = ps_value;
371 break;
373 case ps_value:
374 state = ps_bad;
375 break;
376 #endif /* HANDLE_PRAGMA_WEAK */
378 #ifdef HANDLE_PRAGMA_PACK
379 case ps_pack:
380 state = (strcmp (string, "(") ? ps_bad : ps_left);
381 break;
383 case ps_left:
385 if (token == NULL_TREE)
387 /* #pragma pack () resets packing rules to their
388 defaults. */
389 if (strcmp (string, ")") == 0)
391 align = 0;
392 state = ps_right;
394 else
395 state = ps_bad;
397 else if (TREE_CODE (token) == INTEGER_CST)
398 goto handle_align;
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;
407 else
408 state = ps_bad;
410 #endif
411 else
412 state = ps_bad;
413 break;
415 handle_align:
416 align = TREE_INT_CST_LOW (token);
417 switch (align)
419 case 1:
420 case 2:
421 case 4:
422 case 8:
423 case 16:
424 state = ps_align;
425 break;
427 default:
428 state = ps_bad;
429 break;
431 break;
433 case ps_align:
434 state = (strcmp (string, ")") ? ps_bad : ps_right);
435 break;
437 case ps_right:
438 state = ps_bad;
439 break;
440 #endif /* HANDLE_PRAGMA_PACK */
442 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
443 case ps_push:
444 state = (strcmp (string, ",") ? ps_bad : ps_pushcomma);
445 break;
447 case ps_pushid:
448 state = (strcmp (string, ",") ? ps_bad : ps_pushcomma2);
449 break;
451 case ps_pushcomma:
452 if (token && TREE_CODE (token) == IDENTIFIER_NODE)
454 id = token;
455 state = ps_pushid;
456 break;
459 /* else fall through */
460 case ps_pushcomma2:
461 if (token && TREE_CODE (token) == INTEGER_CST)
462 goto handle_align;
463 else
464 state = ps_bad;
465 break;
467 case ps_pop:
468 if (strcmp (string, ",") == 0)
469 state = ps_popcomma;
470 else
471 state = (strcmp (string, ")") ? ps_bad : ps_right);
472 break;
474 case ps_popcomma:
475 if (token && TREE_CODE (token) == IDENTIFIER_NODE)
477 id = token;
478 state = ps_align;
480 else
481 state = ps_bad;
482 break;
483 #endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
485 case ps_bad:
486 case ps_done:
487 break;
489 default:
490 abort ();
493 return 1;
495 #endif /* HANDLE_GENERIC_PRAGMAS */