Add D30V options
[official-gcc.git] / gcc / c-pragma.c
blob3bb9a390d1aa01f9f97578212588673afa1f2934
1 /* Handle #pragma, system V.4 style. Supports #pragma weak and #pragma pack.
2 Copyright (C) 1992, 1997, 1998, 1999, 2000 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_PUSH_POP
35 typedef struct align_stack
37 int alignment;
38 unsigned int num_pushes;
39 tree id;
40 struct align_stack * prev;
41 } align_stack;
43 static struct align_stack * alignment_stack = NULL;
45 /* If we have a "global" #pragma pack(<n>) if effect when the first
46 #pragma push(pack,<n>) is encountered, this stores the the value of
47 maximum_field_alignment in effect. When the final pop_alignment()
48 happens, we restore the value to this, not to a value of 0 for
49 maximum_field_alignment. Value is in bits. */
50 static int default_alignment;
52 static int push_alignment PARAMS ((int, tree));
53 static int pop_alignment PARAMS ((tree));
54 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
55 static void mark_align_stack PARAMS ((void *));
56 #endif
58 /* Push an alignment value onto the stack. */
59 static int
60 push_alignment (alignment, id)
61 int alignment;
62 tree id;
64 switch (alignment)
66 case 0:
67 case 1:
68 case 2:
69 case 4:
70 case 8:
71 case 16:
72 break;
73 default:
74 warning ("\
75 Alignment must be a small power of two, not %d, in #pragma pack",
76 alignment);
77 return 0;
80 if (alignment_stack == NULL
81 || alignment_stack->alignment != alignment
82 || id != NULL_TREE)
84 align_stack * entry;
86 entry = (align_stack *) xmalloc (sizeof (* entry));
88 entry->alignment = alignment;
89 entry->num_pushes = 1;
90 entry->id = id;
91 entry->prev = alignment_stack;
93 /* The current value of maximum_field_alignment is not necessarily
94 0 since there may be a #pragma pack(<n>) in effect; remember it
95 so that we can restore it after the final #pragma pop(). */
96 if (alignment_stack == NULL)
97 default_alignment = maximum_field_alignment;
99 alignment_stack = entry;
101 maximum_field_alignment = alignment * BITS_PER_UNIT;
103 else
104 alignment_stack->num_pushes ++;
106 return 1;
109 /* Undo a push of an alignment onto the stack. */
110 static int
111 pop_alignment (id)
112 tree id;
114 align_stack * entry;
116 if (alignment_stack == NULL)
118 warning ("\
119 #pragma pack (pop) encountered without matching #pragma pack (push, <n>)"
121 return 0;
124 /* If we got an identifier, strip away everything above the target
125 entry so that the next step will restore the state just below it. */
126 if (id)
128 for (entry = alignment_stack; entry; entry = entry->prev)
129 if (entry->id == id)
131 entry->num_pushes = 1;
132 alignment_stack = entry;
133 break;
135 if (entry == NULL)
136 warning ("\
137 #pragma pack(pop, %s) encountered without matching #pragma pack(push, %s, <n>)"
138 , IDENTIFIER_POINTER (id), IDENTIFIER_POINTER (id));
141 if (-- alignment_stack->num_pushes == 0)
143 entry = alignment_stack->prev;
145 if (entry == NULL)
146 maximum_field_alignment = default_alignment;
147 else
148 maximum_field_alignment = entry->alignment * BITS_PER_UNIT;
150 free (alignment_stack);
152 alignment_stack = entry;
155 return 1;
157 #endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
159 /* Handle one token of a pragma directive. TOKEN is the current token, and
160 STRING is its printable form. Some front ends do not support generating
161 tokens, and will only pass in a STRING. Also some front ends will reuse
162 the buffer containing STRING, so it must be copied to a local buffer if
163 it needs to be preserved.
165 If STRING is non-NULL, then the return value will be ignored, and there
166 will be futher calls to handle_pragma_token in order to handle the rest of
167 the line containing the #pragma directive. If STRING is NULL, the entire
168 line has now been presented to handle_pragma_token and the return value
169 should be zero if the pragma flawed in some way, or if the pragma was not
170 recognised, and non-zero if it was successfully handled. */
173 handle_pragma_token (string, token)
174 const char *string;
175 tree token;
177 static enum pragma_state state = ps_start;
178 static enum pragma_state type;
179 #ifdef HANDLE_PRAGMA_WEAK
180 static char *name;
181 static char *value;
182 #endif
183 #if defined(HANDLE_PRAGMA_PACK) || defined(HANDLE_PRAGMA_PACK_PUSH_POP)
184 static unsigned int align;
185 #endif
186 static tree id;
188 /* If we have reached the end of the #pragma directive then
189 determine what value we should return. */
191 if (string == NULL)
193 int ret_val = 0;
195 switch (type)
197 default:
198 abort ();
199 break;
201 case ps_done:
202 /* The pragma was not recognised. */
203 break;
205 #ifdef HANDLE_PRAGMA_PACK
206 case ps_pack:
207 if (state == ps_right)
209 maximum_field_alignment = align * BITS_PER_UNIT;
210 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
211 default_alignment = maximum_field_alignment;
212 #endif
213 ret_val = 1;
215 else
216 warning ("malformed `#pragma pack'");
217 break;
218 #endif /* HANDLE_PRAGMA_PACK */
220 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
221 case ps_push:
222 if (state == ps_right)
223 ret_val = push_alignment (align, id);
224 else
225 warning ("malformed '#pragma pack(push[,id],<n>)'");
226 break;
228 case ps_pop:
229 if (state == ps_right)
230 ret_val = pop_alignment (id);
231 else
232 warning ("malformed '#pragma pack(pop[,id])'");
233 break;
234 #endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
236 #ifdef HANDLE_PRAGMA_WEAK
237 case ps_weak:
238 if (HANDLE_PRAGMA_WEAK)
240 if (state == ps_name)
241 ret_val = add_weak (name, NULL);
242 else if (state == ps_value)
243 ret_val = add_weak (name, value);
244 else
245 warning ("malformed `#pragma weak'");
247 else
248 ret_val = 1; /* Ignore the pragma. */
249 break;
250 #endif /* HANDLE_PRAGMA_WEAK */
252 case ps_poison:
253 ret_val = 1;
254 break;
257 type = state = ps_start;
258 id = NULL_TREE;
260 return ret_val;
263 /* If we have been given a token, but it is not an identifier,
264 or a small constant, then something has gone wrong. */
265 if (token)
267 switch (TREE_CODE (token))
269 case IDENTIFIER_NODE:
270 break;
272 case INTEGER_CST:
273 if (TREE_INT_CST_HIGH (token) != 0)
274 return 0;
275 break;
277 default:
278 return 0;
282 switch (state)
284 case ps_start:
285 type = state = ps_done;
286 #ifdef HANDLE_PRAGMA_PACK
287 if (strcmp (string, "pack") == 0)
288 type = state = ps_pack;
289 #endif
290 #ifdef HANDLE_PRAGMA_WEAK
291 if (strcmp (string, "weak") == 0)
292 type = state = ps_weak;
293 #endif
294 if (strcmp (string, "poison") == 0)
295 type = state = ps_poison;
296 break;
298 #ifdef HANDLE_PRAGMA_WEAK
299 case ps_weak:
300 name = xstrdup (string);
301 state = ps_name;
302 break;
304 case ps_name:
305 state = (strcmp (string, "=") ? ps_bad : ps_equals);
306 break;
308 case ps_equals:
309 value = xstrdup (string);
310 state = ps_value;
311 break;
313 case ps_value:
314 state = ps_bad;
315 break;
316 #endif /* HANDLE_PRAGMA_WEAK */
318 #ifdef HANDLE_PRAGMA_PACK
319 case ps_pack:
320 state = (strcmp (string, "(") ? ps_bad : ps_left);
321 break;
323 case ps_left:
325 if (token == NULL_TREE)
327 /* #pragma pack () resets packing rules to their
328 defaults. */
329 if (strcmp (string, ")") == 0)
331 align = 0;
332 state = ps_right;
334 else
335 state = ps_bad;
337 else if (TREE_CODE (token) == INTEGER_CST)
338 goto handle_align;
340 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
341 else if (TREE_CODE (token) == IDENTIFIER_NODE)
343 if (strcmp (string, "push") == 0)
344 type = state = ps_push;
345 else if (strcmp (string, "pop") == 0)
346 type = state = ps_pop;
347 else
348 state = ps_bad;
350 #endif
351 else
352 state = ps_bad;
353 break;
355 handle_align:
356 switch (tree_log2 (token))
358 case 0:
359 case 1:
360 case 2:
361 case 3:
362 case 4:
363 state = ps_align;
364 align = 1 << tree_log2 (token);
365 break;
367 default:
368 state = ps_bad;
369 break;
371 break;
373 case ps_align:
374 state = (strcmp (string, ")") ? ps_bad : ps_right);
375 break;
377 case ps_right:
378 state = ps_bad;
379 break;
380 #endif /* HANDLE_PRAGMA_PACK */
382 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
383 case ps_push:
384 state = (strcmp (string, ",") ? ps_bad : ps_pushcomma);
385 break;
387 case ps_pushid:
388 state = (strcmp (string, ",") ? ps_bad : ps_pushcomma2);
389 break;
391 case ps_pushcomma:
392 if (token && TREE_CODE (token) == IDENTIFIER_NODE)
394 id = token;
395 state = ps_pushid;
396 break;
399 /* else fall through */
400 case ps_pushcomma2:
401 if (token && TREE_CODE (token) == INTEGER_CST)
402 goto handle_align;
403 else
404 state = ps_bad;
405 break;
407 case ps_pop:
408 if (strcmp (string, ",") == 0)
409 state = ps_popcomma;
410 else
411 state = (strcmp (string, ")") ? ps_bad : ps_right);
412 break;
414 case ps_popcomma:
415 if (token && TREE_CODE (token) == IDENTIFIER_NODE)
417 id = token;
418 state = ps_align;
420 else
421 state = ps_bad;
422 break;
423 #endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
425 case ps_poison:
426 if (token && TREE_CODE (token) != IDENTIFIER_NODE)
427 state = ps_bad;
428 break;
430 case ps_bad:
431 case ps_done:
432 break;
434 default:
435 abort ();
438 return 1;
440 #endif /* HANDLE_GENERIC_PRAGMAS */
442 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
443 static void
444 mark_align_stack (p)
445 void *p;
447 align_stack *a = *(align_stack **) p;
449 while (a)
451 ggc_mark_tree (a->id);
452 a = a->prev;
455 #endif
457 void
458 init_pragma ()
460 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
461 ggc_add_root (&alignment_stack, 1, sizeof(alignment_stack),
462 mark_align_stack);
463 #endif