]> gcc.gnu.org Git - gcc.git/blame - gcc/c-pragma.c
ppc-asm.h (FUNC_START): Use USER_LABEL_PREFIX.
[gcc.git] / gcc / c-pragma.c
CommitLineData
a187ac95 1/* Handle #pragma, system V.4 style. Supports #pragma weak and #pragma pack.
6e090c76 2 Copyright (C) 1992, 97-99, 2000 Free Software Foundation, Inc.
a187ac95
RS
3
4This file is part of GNU CC.
5
6GNU CC is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11GNU CC is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU CC; see the file COPYING. If not, write to
940d9d63
RK
18the Free Software Foundation, 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA. */
a187ac95 20
4b578ebf 21#include "config.h"
670ee920 22#include "system.h"
d05a5492 23#include "rtl.h"
4b578ebf 24#include "tree.h"
ca695ac9 25#include "function.h"
6be160ff 26#include "defaults.h"
3d6f7931 27#include "c-pragma.h"
750caf0d 28#include "flags.h"
5f6da302 29#include "toplev.h"
da9da134 30#include "ggc.h"
4b578ebf 31
e2af664c 32#ifdef HANDLE_GENERIC_PRAGMAS
a187ac95 33
e2af664c 34#ifdef HANDLE_PRAGMA_PACK
a187ac95
RS
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
0f41302f 37 in effect, this is zero. */
a187ac95
RS
38
39extern int maximum_field_alignment;
e2af664c
NC
40#endif
41
42
43#ifdef HANDLE_PRAGMA_PACK_PUSH_POP
44typedef struct align_stack
45{
46 int alignment;
47 unsigned int num_pushes;
0f92adae 48 tree id;
e2af664c
NC
49 struct align_stack * prev;
50} align_stack;
51
52static struct align_stack * alignment_stack = NULL;
53
61e8b354
MK
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. */
59static int default_alignment;
60
6e090c76
KG
61static int push_alignment PARAMS ((int, tree));
62static int pop_alignment PARAMS ((tree));
e2af664c
NC
63
64/* Push an alignment value onto the stack. */
65static int
0f92adae 66push_alignment (alignment, id)
e2af664c 67 int alignment;
0f92adae 68 tree id;
e2af664c
NC
69{
70 switch (alignment)
71 {
72 case 0:
73 case 1:
74 case 2:
75 case 4:
76 case 8:
77 case 16:
78 break;
79 default:
80 warning ("\
81Alignment must be a small power of two, not %d, in #pragma pack",
82 alignment);
83 return 0;
84 }
85
86 if (alignment_stack == NULL
0f92adae
JM
87 || alignment_stack->alignment != alignment
88 || id != NULL_TREE)
e2af664c
NC
89 {
90 align_stack * entry;
91
92 entry = (align_stack *) xmalloc (sizeof (* entry));
93
e2af664c
NC
94 entry->alignment = alignment;
95 entry->num_pushes = 1;
0f92adae 96 entry->id = id;
e2af664c
NC
97 entry->prev = alignment_stack;
98
61e8b354
MK
99 /* The current value of maximum_field_alignment is not necessarily
100 0 since there may be a #pragma pack(<n>) in effect; remember it
101 so that we can restore it after the final #pragma pop(). */
102 if (alignment_stack == NULL)
103 default_alignment = maximum_field_alignment;
104
e2af664c
NC
105 alignment_stack = entry;
106
0f92adae 107 maximum_field_alignment = alignment * 8;
e2af664c
NC
108 }
109 else
110 alignment_stack->num_pushes ++;
111
112 return 1;
113}
114
115/* Undo a push of an alignment onto the stack. */
116static int
0f92adae
JM
117pop_alignment (id)
118 tree id;
e2af664c 119{
0f92adae
JM
120 align_stack * entry;
121
e2af664c
NC
122 if (alignment_stack == NULL)
123 {
124 warning ("\
0f92adae
JM
125#pragma pack (pop) encountered without matching #pragma pack (push, <n>)"
126 );
e2af664c
NC
127 return 0;
128 }
129
0f92adae
JM
130 /* If we got an identifier, strip away everything above the target
131 entry so that the next step will restore the state just below it. */
132 if (id)
133 {
134 for (entry = alignment_stack; entry; entry = entry->prev)
135 if (entry->id == id)
136 {
137 entry->num_pushes = 1;
138 alignment_stack = entry;
139 break;
140 }
141 if (entry == NULL)
142 warning ("\
143#pragma pack(pop, %s) encountered without matching #pragma pack(push, %s, <n>)"
144 , IDENTIFIER_POINTER (id), IDENTIFIER_POINTER (id));
145 }
146
e2af664c
NC
147 if (-- alignment_stack->num_pushes == 0)
148 {
e2af664c
NC
149 entry = alignment_stack->prev;
150
224bb373 151 if (entry == NULL)
61e8b354 152 maximum_field_alignment = default_alignment;
e2af664c
NC
153 else
154 maximum_field_alignment = entry->alignment * 8;
155
156 free (alignment_stack);
157
158 alignment_stack = entry;
159 }
160
161 return 1;
162}
e2af664c
NC
163#endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
164\f
e2af664c
NC
165/* Handle one token of a pragma directive. TOKEN is the current token, and
166 STRING is its printable form. Some front ends do not support generating
167 tokens, and will only pass in a STRING. Also some front ends will reuse
168 the buffer containing STRING, so it must be copied to a local buffer if
169 it needs to be preserved.
170
171 If STRING is non-NULL, then the return value will be ignored, and there
172 will be futher calls to handle_pragma_token() in order to handle the rest of
173 the line containing the #pragma directive. If STRING is NULL, the entire
174 line has now been presented to handle_pragma_token() and the return value
175 should be zero if the pragma flawed in some way, or if the pragma was not
176 recognised, and non-zero if it was successfully handled. */
a187ac95 177
f09db6e0 178int
a187ac95 179handle_pragma_token (string, token)
5d5993dd 180 const char * string;
a187ac95
RS
181 tree token;
182{
e2af664c
NC
183 static enum pragma_state state = ps_start;
184 static enum pragma_state type;
341a243e 185#ifdef HANDLE_PRAGMA_WEAK
e2af664c
NC
186 static char * name;
187 static char * value;
341a243e
KG
188#endif
189#if defined(HANDLE_PRAGMA_PACK) || defined(HANDLE_PRAGMA_PACK_PUSH_POP)
a187ac95 190 static int align;
341a243e 191#endif
0f92adae 192 static tree id;
a187ac95 193
e2af664c
NC
194 /* If we have reached the end of the #pragma directive then
195 determine what value we should return. */
196
f09db6e0 197 if (string == NULL)
a187ac95 198 {
e2af664c
NC
199 int ret_val = 0;
200
201 switch (type)
a187ac95 202 {
e2af664c
NC
203 default:
204 abort ();
205 break;
206
207 case ps_done:
208 /* The pragma was not recognised. */
209 break;
210
211#ifdef HANDLE_PRAGMA_PACK
212 case ps_pack:
a187ac95 213 if (state == ps_right)
f09db6e0 214 {
e2af664c 215 maximum_field_alignment = align * 8;
61e8b354
MK
216#ifdef HANDLE_PRAGMA_PACK_PUSH_POP
217 default_alignment = maximum_field_alignment;
218#endif
e2af664c 219 ret_val = 1;
f09db6e0 220 }
e2af664c
NC
221 else
222 warning ("malformed `#pragma pack'");
223 break;
224#endif /* HANDLE_PRAGMA_PACK */
225
226#ifdef HANDLE_PRAGMA_PACK_PUSH_POP
227 case ps_push:
228 if (state == ps_right)
0f92adae 229 ret_val = push_alignment (align, id);
e2af664c 230 else
0f92adae 231 warning ("malformed '#pragma pack(push[,id],<n>)'");
e2af664c
NC
232 break;
233
234 case ps_pop:
235 if (state == ps_right)
0f92adae 236 ret_val = pop_alignment (id);
e2af664c 237 else
0f92adae 238 warning ("malformed '#pragma pack(pop[,id])'");
e2af664c
NC
239 break;
240#endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
241
a3100298 242#ifdef HANDLE_PRAGMA_WEAK
e2af664c 243 case ps_weak:
a3100298 244 if (HANDLE_PRAGMA_WEAK)
e2af664c
NC
245 {
246 if (state == ps_name)
247 ret_val = add_weak (name, NULL);
248 else if (state == ps_value)
249 ret_val = add_weak (name, value);
250 else
251 warning ("malformed `#pragma weak'");
252 }
253 else
254 ret_val = 1; /* Ignore the pragma. */
255 break;
d300e551 256#endif /* HANDLE_PRAGMA_WEAK */
fc009f96
GK
257
258 case ps_poison:
259 ret_val = 1;
260 break;
a187ac95 261 }
a187ac95
RS
262
263 type = state = ps_start;
0f92adae 264 id = NULL_TREE;
f09db6e0
NC
265
266 return ret_val;
a187ac95
RS
267 }
268
e2af664c
NC
269 /* If we have been given a token, but it is not an identifier,
270 or a small constant, then something has gone wrong. */
271 if (token)
272 {
273 switch (TREE_CODE (token))
274 {
275 case IDENTIFIER_NODE:
276 break;
277
278 case INTEGER_CST:
279 if (TREE_INT_CST_HIGH (token) != 0)
280 return 0;
281 break;
282
283 default:
284 return 0;
285 }
286 }
287
a187ac95
RS
288 switch (state)
289 {
290 case ps_start:
e2af664c
NC
291 type = state = ps_done;
292#ifdef HANDLE_PRAGMA_PACK
293 if (strcmp (string, "pack") == 0)
294 type = state = ps_pack;
295#endif
f09db6e0 296#ifdef HANDLE_PRAGMA_WEAK
e2af664c
NC
297 if (strcmp (string, "weak") == 0)
298 type = state = ps_weak;
fc009f96
GK
299#endif
300 if (strcmp (string, "poison") == 0)
301 type = state = ps_poison;
a187ac95 302 break;
fc009f96 303
f09db6e0 304#ifdef HANDLE_PRAGMA_WEAK
a187ac95 305 case ps_weak:
4dd7201e
ZW
306 name = xstrdup (string);
307 state = ps_name;
a187ac95 308 break;
f09db6e0 309
a187ac95
RS
310 case ps_name:
311 state = (strcmp (string, "=") ? ps_bad : ps_equals);
312 break;
313
314 case ps_equals:
4dd7201e
ZW
315 value = xstrdup (string);
316 state = ps_value;
a187ac95
RS
317 break;
318
319 case ps_value:
320 state = ps_bad;
321 break;
e2af664c
NC
322#endif /* HANDLE_PRAGMA_WEAK */
323
324#ifdef HANDLE_PRAGMA_PACK
a187ac95 325 case ps_pack:
e2af664c 326 state = (strcmp (string, "(") ? ps_bad : ps_left);
a187ac95
RS
327 break;
328
329 case ps_left:
7169a029 330
0f92adae 331 if (token == NULL_TREE)
3cc0b551
MK
332 {
333 /* #pragma pack () resets packing rules to their
334 defaults. */
335 if (strcmp (string, ")") == 0)
336 {
337 align = 0;
338 state = ps_right;
339 }
340 else
341 state = ps_bad;
342 }
0f92adae
JM
343 else if (TREE_CODE (token) == INTEGER_CST)
344 goto handle_align;
345
346#ifdef HANDLE_PRAGMA_PACK_PUSH_POP
347 else if (TREE_CODE (token) == IDENTIFIER_NODE)
348 {
349 if (strcmp (string, "push") == 0)
350 type = state = ps_push;
351 else if (strcmp (string, "pop") == 0)
352 type = state = ps_pop;
353 else
354 state = ps_bad;
355 }
356#endif
7169a029 357 else
0f92adae
JM
358 state = ps_bad;
359 break;
360
361 handle_align:
362 align = TREE_INT_CST_LOW (token);
e2af664c 363 switch (align)
a187ac95 364 {
e2af664c
NC
365 case 1:
366 case 2:
367 case 4:
0f92adae
JM
368 case 8:
369 case 16:
e2af664c
NC
370 state = ps_align;
371 break;
372
e2af664c
NC
373 default:
374 state = ps_bad;
375 break;
a187ac95 376 }
a187ac95
RS
377 break;
378
379 case ps_align:
e2af664c 380 state = (strcmp (string, ")") ? ps_bad : ps_right);
a187ac95
RS
381 break;
382
383 case ps_right:
384 state = ps_bad;
385 break;
e2af664c 386#endif /* HANDLE_PRAGMA_PACK */
a187ac95 387
e2af664c
NC
388#ifdef HANDLE_PRAGMA_PACK_PUSH_POP
389 case ps_push:
0f92adae 390 state = (strcmp (string, ",") ? ps_bad : ps_pushcomma);
e2af664c
NC
391 break;
392
0f92adae
JM
393 case ps_pushid:
394 state = (strcmp (string, ",") ? ps_bad : ps_pushcomma2);
395 break;
396
397 case ps_pushcomma:
398 if (token && TREE_CODE (token) == IDENTIFIER_NODE)
399 {
400 id = token;
401 state = ps_pushid;
402 break;
403 }
404
405 /* else fall through */
406 case ps_pushcomma2:
407 if (token && TREE_CODE (token) == INTEGER_CST)
408 goto handle_align;
409 else
410 state = ps_bad;
411 break;
412
413 case ps_pop:
414 if (strcmp (string, ",") == 0)
415 state = ps_popcomma;
416 else
417 state = (strcmp (string, ")") ? ps_bad : ps_right);
418 break;
419
420 case ps_popcomma:
421 if (token && TREE_CODE (token) == IDENTIFIER_NODE)
422 {
423 id = token;
424 state = ps_align;
425 }
426 else
427 state = ps_bad;
e2af664c
NC
428 break;
429#endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
fc009f96
GK
430
431 case ps_poison:
432 if (token && TREE_CODE (token) != IDENTIFIER_NODE)
433 state = ps_bad;
434 break;
435
a187ac95
RS
436 case ps_bad:
437 case ps_done:
438 break;
439
440 default:
441 abort ();
442 }
f09db6e0
NC
443
444 return 1;
a187ac95 445}
e2af664c 446#endif /* HANDLE_GENERIC_PRAGMAS */
568767a6
RH
447\f
448#ifdef HANDLE_PRAGMA_PACK_PUSH_POP
449static void
450mark_align_stack (p)
451 void *p;
452{
2cccc340 453 align_stack *a = *(align_stack **) p;
568767a6
RH
454
455 while (a)
456 {
457 ggc_mark_tree (a->id);
458 a = a->prev;
459 }
460}
461#endif
462
463void
464init_pragma ()
465{
466#ifdef HANDLE_PRAGMA_PACK_PUSH_POP
467 ggc_add_root (&alignment_stack, 1, sizeof(alignment_stack),
468 mark_align_stack);
469#endif
470}
This page took 0.589443 seconds and 5 git commands to generate.