OSDN Git Service

Document that CC1_SPEC is used by cc1plus
[pf3gnuchains/gcc-fork.git] / gcc / c-pragma.c
1 /* Handle #pragma, system V.4 style.  Supports #pragma weak and #pragma pack.
2    Copyright (C) 1992, 1997, 1998, 1999 Free Software Foundation, Inc.
3
4 This file is part of GNU CC.
5
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.
10
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.
15
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.  */
20
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"
31
32 #ifdef HANDLE_GENERIC_PRAGMAS
33
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.  */
38
39 extern int maximum_field_alignment;
40 #endif
41
42
43 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
44 typedef struct align_stack
45 {
46   int                  alignment;
47   unsigned int         num_pushes;
48   tree                 id;
49   struct align_stack * prev;
50 } align_stack;
51
52 static struct align_stack * alignment_stack = NULL;
53
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;
60
61 static int  push_alignment PROTO((int, tree));
62 static int  pop_alignment  PROTO((tree));
63
64 /* Push an alignment value onto the stack.  */
65 static int
66 push_alignment (alignment, id)
67      int alignment;
68      tree id;
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 ("\
81 Alignment must be a small power of two, not %d, in #pragma pack",
82                alignment);
83       return 0;
84     }
85   
86   if (alignment_stack == NULL
87       || alignment_stack->alignment != alignment
88       || id != NULL_TREE)
89     {
90       align_stack * entry;
91
92       entry = (align_stack *) xmalloc (sizeof (* entry));
93
94       entry->alignment  = alignment;
95       entry->num_pushes = 1;
96       entry->id         = id;
97       entry->prev       = alignment_stack;
98       
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       
105       alignment_stack = entry;
106
107       maximum_field_alignment = alignment * 8;
108     }
109   else
110     alignment_stack->num_pushes ++;
111
112   return 1;
113 }
114
115 /* Undo a push of an alignment onto the stack.  */
116 static int
117 pop_alignment (id)
118      tree id;
119 {
120   align_stack * entry;
121       
122   if (alignment_stack == NULL)
123     {
124       warning ("\
125 #pragma pack (pop) encountered without matching #pragma pack (push, <n>)"
126                );
127       return 0;
128     }
129
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
147   if (-- alignment_stack->num_pushes == 0)
148     {
149       entry = alignment_stack->prev;
150
151       if (entry == NULL)
152         maximum_field_alignment = default_alignment;
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 }
163 #endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
164 \f
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.  */
177
178 int
179 handle_pragma_token (string, token)
180      const char * string;
181      tree token;
182 {
183   static enum pragma_state state = ps_start;
184   static enum pragma_state type;
185 #ifdef HANDLE_PRAGMA_WEAK
186   static char * name;
187   static char * value;
188 #endif
189 #if defined(HANDLE_PRAGMA_PACK) || defined(HANDLE_PRAGMA_PACK_PUSH_POP)
190   static int align;
191 #endif
192   static tree id;
193
194   /* If we have reached the end of the #pragma directive then
195      determine what value we should return.  */
196   
197   if (string == NULL)
198     {
199       int ret_val = 0;
200
201       switch (type)
202         {
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:
213           if (state == ps_right)
214             {
215               maximum_field_alignment = align * 8;
216 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
217               default_alignment = maximum_field_alignment;
218 #endif
219               ret_val = 1;
220             }
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)
229             ret_val = push_alignment (align, id);
230           else
231             warning ("malformed '#pragma pack(push[,id],<n>)'");
232           break;
233           
234         case ps_pop:
235           if (state == ps_right)
236             ret_val = pop_alignment (id);
237           else
238             warning ("malformed '#pragma pack(pop[,id])'");
239           break;
240 #endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
241           
242 #ifdef HANDLE_PRAGMA_WEAK
243         case ps_weak:
244           if (HANDLE_PRAGMA_WEAK)
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;
256 #endif /* HANDLE_PRAGMA_WEAK */
257
258         case ps_poison:
259           ret_val = 1;
260           break;
261         }
262
263       type = state = ps_start;
264       id = NULL_TREE;
265       
266       return ret_val;
267     }
268
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       
288   switch (state)
289     {
290     case ps_start:
291       type = state = ps_done;
292 #ifdef HANDLE_PRAGMA_PACK
293       if (strcmp (string, "pack") == 0)
294         type = state = ps_pack;
295 #endif
296 #ifdef HANDLE_PRAGMA_WEAK
297       if (strcmp (string, "weak") == 0)
298         type = state = ps_weak;
299 #endif
300       if (strcmp (string, "poison") == 0)
301         type = state = ps_poison;
302       break;
303
304 #ifdef HANDLE_PRAGMA_WEAK
305     case ps_weak:
306       name = permalloc (strlen (string) + 1);
307       if (name == NULL)
308         {
309           warning ("Out of memory parsing #pragma weak");
310           state = ps_bad;
311         }
312       else
313         {
314           strcpy (name, string);
315           state = ps_name;
316         }
317       break;
318       
319     case ps_name:
320       state = (strcmp (string, "=") ? ps_bad : ps_equals);
321       break;
322
323     case ps_equals:
324       value = permalloc (strlen (string) + 1);
325       if (value == NULL)
326         {
327           warning ("Out of memory parsing #pragma weak");
328           state = ps_bad;
329         }
330       else
331         {
332           strcpy (value, string);
333           state = ps_value;
334         }
335       break;
336
337     case ps_value:
338       state = ps_bad;
339       break;
340 #endif /* HANDLE_PRAGMA_WEAK */
341       
342 #ifdef HANDLE_PRAGMA_PACK
343     case ps_pack:
344       state = (strcmp (string, "(") ? ps_bad : ps_left);
345       break;
346
347     case ps_left:
348
349       if (token == NULL_TREE)
350         {
351           /* #pragma pack () resets packing rules to their
352              defaults.  */
353           if (strcmp (string, ")") == 0)
354             {
355               align = 0;
356               state = ps_right;
357             }
358           else
359             state = ps_bad;
360         }
361       else if (TREE_CODE (token) == INTEGER_CST)
362         goto handle_align;
363
364 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
365       else if (TREE_CODE (token) == IDENTIFIER_NODE)
366         {
367           if (strcmp (string, "push") == 0)
368             type = state = ps_push;
369           else if (strcmp (string, "pop") == 0)
370             type = state = ps_pop;
371           else
372             state = ps_bad;
373         }
374 #endif
375       else
376         state = ps_bad;
377       break;
378
379     handle_align:
380       align = TREE_INT_CST_LOW (token);
381       switch (align)
382         {
383         case 1:
384         case 2:
385         case 4:
386         case 8:
387         case 16:
388           state = ps_align;
389           break;
390
391         default:
392           state = ps_bad;
393           break;
394         }
395       break;
396
397     case ps_align:
398       state = (strcmp (string, ")") ? ps_bad : ps_right);
399       break;
400
401     case ps_right:
402       state = ps_bad;
403       break;
404 #endif /* HANDLE_PRAGMA_PACK */
405
406 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
407     case ps_push:
408       state = (strcmp (string, ",") ? ps_bad : ps_pushcomma);
409       break;
410
411     case ps_pushid:
412       state = (strcmp (string, ",") ? ps_bad : ps_pushcomma2);
413       break;
414
415     case ps_pushcomma:
416       if (token && TREE_CODE (token) == IDENTIFIER_NODE)
417         {
418           id = token;
419           state = ps_pushid;
420           break;
421         }
422
423       /* else fall through */
424     case ps_pushcomma2:
425       if (token && TREE_CODE (token) == INTEGER_CST)
426         goto handle_align;
427       else
428         state = ps_bad;
429       break;
430
431     case ps_pop:
432       if (strcmp (string, ",") == 0)
433         state = ps_popcomma;
434       else
435         state = (strcmp (string, ")") ? ps_bad : ps_right);
436       break;
437
438     case ps_popcomma:
439       if (token && TREE_CODE (token) == IDENTIFIER_NODE)
440         {
441           id = token;
442           state = ps_align;
443         }
444       else
445         state = ps_bad;
446       break;
447 #endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
448
449     case ps_poison:
450       if (token && TREE_CODE (token) != IDENTIFIER_NODE)
451         state = ps_bad;
452       break;
453
454     case ps_bad:
455     case ps_done:
456       break;
457
458     default:
459       abort ();
460     }
461
462   return 1;
463 }
464 #endif /* HANDLE_GENERIC_PRAGMAS */
465 \f
466 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
467 static void
468 mark_align_stack (p)
469     void *p;
470 {
471   align_stack *a = *(align_stack **) p;
472
473   while (a)
474     {
475       ggc_mark_tree (a->id);
476       a = a->prev;
477     }
478 }
479 #endif
480
481 void
482 init_pragma ()
483 {
484 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
485   ggc_add_root (&alignment_stack, 1, sizeof(alignment_stack),
486                 mark_align_stack);
487 #endif
488 }