* config/mips/iris6.h (SUBTARGET_ASM_OPTIMIZING_SPEC): Define to
[official-gcc.git] / gcc / c-pragma.c
blob36aa2c4dbaf07dfe9227c82ef23ce86d78f9e4c7
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 "function.h"
26 #include "defaults.h"
27 #include "c-pragma.h"
28 #include "flags.h"
29 #include "toplev.h"
30 #include "ggc.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 /* If we have a "global" #pragma pack(<n>) if effect when the first
55 #pragma push(pack,<n>) is encountered, this stores the the value of
56 maximum_field_alignment in effect. When the final pop_alignment()
57 happens, we restore the value to this, not to a value of 0 for
58 maximum_field_alignment. Value is in bits. */
59 static int default_alignment;
61 static int push_alignment PROTO((int, tree));
62 static int pop_alignment PROTO((tree));
64 /* Push an alignment value onto the stack. */
65 static int
66 push_alignment (alignment, id)
67 int alignment;
68 tree id;
70 switch (alignment)
72 case 0:
73 case 1:
74 case 2:
75 case 4:
76 case 8:
77 case 16:
78 break;
79 default:
80 warning ("\
81 Alignment must be a small power of two, not %d, in #pragma pack",
82 alignment);
83 return 0;
86 if (alignment_stack == NULL
87 || alignment_stack->alignment != alignment
88 || id != NULL_TREE)
90 align_stack * entry;
92 entry = (align_stack *) xmalloc (sizeof (* entry));
94 if (entry == NULL)
96 warning ("Out of memory pushing #pragma pack");
97 return 0;
100 entry->alignment = alignment;
101 entry->num_pushes = 1;
102 entry->id = id;
103 entry->prev = alignment_stack;
105 /* The current value of maximum_field_alignment is not necessarily
106 0 since there may be a #pragma pack(<n>) in effect; remember it
107 so that we can restore it after the final #pragma pop(). */
108 if (alignment_stack == NULL)
109 default_alignment = maximum_field_alignment;
111 alignment_stack = entry;
113 maximum_field_alignment = alignment * 8;
115 else
116 alignment_stack->num_pushes ++;
118 return 1;
121 /* Undo a push of an alignment onto the stack. */
122 static int
123 pop_alignment (id)
124 tree id;
126 align_stack * entry;
128 if (alignment_stack == NULL)
130 warning ("\
131 #pragma pack (pop) encountered without matching #pragma pack (push, <n>)"
133 return 0;
136 /* If we got an identifier, strip away everything above the target
137 entry so that the next step will restore the state just below it. */
138 if (id)
140 for (entry = alignment_stack; entry; entry = entry->prev)
141 if (entry->id == id)
143 entry->num_pushes = 1;
144 alignment_stack = entry;
145 break;
147 if (entry == NULL)
148 warning ("\
149 #pragma pack(pop, %s) encountered without matching #pragma pack(push, %s, <n>)"
150 , IDENTIFIER_POINTER (id), IDENTIFIER_POINTER (id));
153 if (-- alignment_stack->num_pushes == 0)
155 entry = alignment_stack->prev;
157 if (entry == NULL)
158 maximum_field_alignment = default_alignment;
159 else
160 maximum_field_alignment = entry->alignment * 8;
162 free (alignment_stack);
164 alignment_stack = entry;
167 return 1;
169 #endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
171 /* Handle one token of a pragma directive. TOKEN is the current token, and
172 STRING is its printable form. Some front ends do not support generating
173 tokens, and will only pass in a STRING. Also some front ends will reuse
174 the buffer containing STRING, so it must be copied to a local buffer if
175 it needs to be preserved.
177 If STRING is non-NULL, then the return value will be ignored, and there
178 will be futher calls to handle_pragma_token() in order to handle the rest of
179 the line containing the #pragma directive. If STRING is NULL, the entire
180 line has now been presented to handle_pragma_token() and the return value
181 should be zero if the pragma flawed in some way, or if the pragma was not
182 recognised, and non-zero if it was successfully handled. */
185 handle_pragma_token (string, token)
186 const char * string;
187 tree token;
189 static enum pragma_state state = ps_start;
190 static enum pragma_state type;
191 #ifdef HANDLE_PRAGMA_WEAK
192 static char * name;
193 static char * value;
194 #endif
195 #if defined(HANDLE_PRAGMA_PACK) || defined(HANDLE_PRAGMA_PACK_PUSH_POP)
196 static int align;
197 #endif
198 static tree id;
200 /* If we have reached the end of the #pragma directive then
201 determine what value we should return. */
203 if (string == NULL)
205 int ret_val = 0;
207 switch (type)
209 default:
210 abort ();
211 break;
213 case ps_done:
214 /* The pragma was not recognised. */
215 break;
217 #ifdef HANDLE_PRAGMA_PACK
218 case ps_pack:
219 if (state == ps_right)
221 maximum_field_alignment = align * 8;
222 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
223 default_alignment = maximum_field_alignment;
224 #endif
225 ret_val = 1;
227 else
228 warning ("malformed `#pragma pack'");
229 break;
230 #endif /* HANDLE_PRAGMA_PACK */
232 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
233 case ps_push:
234 if (state == ps_right)
235 ret_val = push_alignment (align, id);
236 else
237 warning ("malformed '#pragma pack(push[,id],<n>)'");
238 break;
240 case ps_pop:
241 if (state == ps_right)
242 ret_val = pop_alignment (id);
243 else
244 warning ("malformed '#pragma pack(pop[,id])'");
245 break;
246 #endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
248 #ifdef HANDLE_PRAGMA_WEAK
249 case ps_weak:
250 if (HANDLE_PRAGMA_WEAK)
252 if (state == ps_name)
253 ret_val = add_weak (name, NULL);
254 else if (state == ps_value)
255 ret_val = add_weak (name, value);
256 else
257 warning ("malformed `#pragma weak'");
259 else
260 ret_val = 1; /* Ignore the pragma. */
261 break;
262 #endif /* HANDLE_PRAGMA_WEAK */
264 case ps_poison:
265 ret_val = 1;
266 break;
269 type = state = ps_start;
270 id = NULL_TREE;
272 return ret_val;
275 /* If we have been given a token, but it is not an identifier,
276 or a small constant, then something has gone wrong. */
277 if (token)
279 switch (TREE_CODE (token))
281 case IDENTIFIER_NODE:
282 break;
284 case INTEGER_CST:
285 if (TREE_INT_CST_HIGH (token) != 0)
286 return 0;
287 break;
289 default:
290 return 0;
294 switch (state)
296 case ps_start:
297 type = state = ps_done;
298 #ifdef HANDLE_PRAGMA_PACK
299 if (strcmp (string, "pack") == 0)
300 type = state = ps_pack;
301 #endif
302 #ifdef HANDLE_PRAGMA_WEAK
303 if (strcmp (string, "weak") == 0)
304 type = state = ps_weak;
305 #endif
306 if (strcmp (string, "poison") == 0)
307 type = state = ps_poison;
308 break;
310 #ifdef HANDLE_PRAGMA_WEAK
311 case ps_weak:
312 name = permalloc (strlen (string) + 1);
313 if (name == NULL)
315 warning ("Out of memory parsing #pragma weak");
316 state = ps_bad;
318 else
320 strcpy (name, string);
321 state = ps_name;
323 break;
325 case ps_name:
326 state = (strcmp (string, "=") ? ps_bad : ps_equals);
327 break;
329 case ps_equals:
330 value = permalloc (strlen (string) + 1);
331 if (value == NULL)
333 warning ("Out of memory parsing #pragma weak");
334 state = ps_bad;
336 else
338 strcpy (value, string);
339 state = ps_value;
341 break;
343 case ps_value:
344 state = ps_bad;
345 break;
346 #endif /* HANDLE_PRAGMA_WEAK */
348 #ifdef HANDLE_PRAGMA_PACK
349 case ps_pack:
350 state = (strcmp (string, "(") ? ps_bad : ps_left);
351 break;
353 case ps_left:
355 if (token == NULL_TREE)
357 /* #pragma pack () resets packing rules to their
358 defaults. */
359 if (strcmp (string, ")") == 0)
361 align = 0;
362 state = ps_right;
364 else
365 state = ps_bad;
367 else if (TREE_CODE (token) == INTEGER_CST)
368 goto handle_align;
370 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
371 else if (TREE_CODE (token) == IDENTIFIER_NODE)
373 if (strcmp (string, "push") == 0)
374 type = state = ps_push;
375 else if (strcmp (string, "pop") == 0)
376 type = state = ps_pop;
377 else
378 state = ps_bad;
380 #endif
381 else
382 state = ps_bad;
383 break;
385 handle_align:
386 align = TREE_INT_CST_LOW (token);
387 switch (align)
389 case 1:
390 case 2:
391 case 4:
392 case 8:
393 case 16:
394 state = ps_align;
395 break;
397 default:
398 state = ps_bad;
399 break;
401 break;
403 case ps_align:
404 state = (strcmp (string, ")") ? ps_bad : ps_right);
405 break;
407 case ps_right:
408 state = ps_bad;
409 break;
410 #endif /* HANDLE_PRAGMA_PACK */
412 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
413 case ps_push:
414 state = (strcmp (string, ",") ? ps_bad : ps_pushcomma);
415 break;
417 case ps_pushid:
418 state = (strcmp (string, ",") ? ps_bad : ps_pushcomma2);
419 break;
421 case ps_pushcomma:
422 if (token && TREE_CODE (token) == IDENTIFIER_NODE)
424 id = token;
425 state = ps_pushid;
426 break;
429 /* else fall through */
430 case ps_pushcomma2:
431 if (token && TREE_CODE (token) == INTEGER_CST)
432 goto handle_align;
433 else
434 state = ps_bad;
435 break;
437 case ps_pop:
438 if (strcmp (string, ",") == 0)
439 state = ps_popcomma;
440 else
441 state = (strcmp (string, ")") ? ps_bad : ps_right);
442 break;
444 case ps_popcomma:
445 if (token && TREE_CODE (token) == IDENTIFIER_NODE)
447 id = token;
448 state = ps_align;
450 else
451 state = ps_bad;
452 break;
453 #endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
455 case ps_poison:
456 if (token && TREE_CODE (token) != IDENTIFIER_NODE)
457 state = ps_bad;
458 break;
460 case ps_bad:
461 case ps_done:
462 break;
464 default:
465 abort ();
468 return 1;
470 #endif /* HANDLE_GENERIC_PRAGMAS */
472 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
473 static void
474 mark_align_stack (p)
475 void *p;
477 align_stack *a = *(align_stack **) p;
479 while (a)
481 ggc_mark_tree (a->id);
482 a = a->prev;
485 #endif
487 void
488 init_pragma ()
490 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
491 ggc_add_root (&alignment_stack, 1, sizeof(alignment_stack),
492 mark_align_stack);
493 #endif