OSDN Git Service

90edeb744a116593532bd0ffd0037f9f3d900d12
[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 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 "except.h"
26 #include "function.h"
27 #include "defaults.h"
28 #include "c-pragma.h"
29 #include "flags.h"
30 #include "toplev.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   struct align_stack * prev;
49 } align_stack;
50
51 static struct align_stack * alignment_stack = NULL;
52
53 static int  push_alignment PROTO((int));
54 static int  pop_alignment  PROTO((void));
55
56 /* Push an alignment value onto the stack.  */
57 static int
58 push_alignment (alignment)
59      int alignment;
60 {
61   switch (alignment)
62     {
63     case 0:
64     case 1:
65     case 2:
66     case 4:
67     case 8:
68     case 16:
69       break;
70     default:
71       warning ("\
72 Alignment must be a small power of two, not %d, in #pragma pack",
73                alignment);
74       return 0;
75     }
76   
77   if (alignment_stack == NULL
78       || alignment_stack->alignment != alignment)
79     {
80       align_stack * entry;
81
82       entry = (align_stack *) xmalloc (sizeof (* entry));
83
84       if (entry == NULL)
85         {
86           warning ("Out of memory pushing #pragma pack");
87           return 0;
88         }
89
90       entry->alignment  = alignment;
91       entry->num_pushes = 1;
92       entry->prev       = alignment_stack;
93       
94       alignment_stack = entry;
95
96       if (alignment < 8)
97         maximum_field_alignment = alignment * 8;
98       else
99         /* MSVC ignores alignments > 4.  */
100         maximum_field_alignment = 0;
101     }
102   else
103     alignment_stack->num_pushes ++;
104
105   return 1;
106 }
107
108 /* Undo a push of an alignment onto the stack.  */
109 static int
110 pop_alignment ()
111 {
112   if (alignment_stack == NULL)
113     {
114       warning ("\
115 #pragma pack(pop) encountered without corresponding #pragma pack(push,<n>)");
116       return 0;
117     }
118
119   if (-- alignment_stack->num_pushes == 0)
120     {
121       align_stack * entry;
122       
123       entry = alignment_stack->prev;
124
125       if (entry == NULL || entry->alignment > 4)
126         maximum_field_alignment = 0;
127       else
128         maximum_field_alignment = entry->alignment * 8;
129
130       free (alignment_stack);
131
132       alignment_stack = entry;
133     }
134
135   return 1;
136 }
137
138 /* Generate 'packed' and 'aligned' attributes for decls whilst a
139    #pragma pack(push... is in effect.  */
140 void
141 insert_pack_attributes (node, attributes, prefix)
142      tree node;
143      tree * attributes;
144      tree * prefix;
145 {
146   tree a;
147
148   /* If we are not packing, then there is nothing to do.  */
149   if (maximum_field_alignment == 0)
150     return;
151
152   /* We are only interested in fields.  */
153   if (TREE_CODE_CLASS (TREE_CODE (node)) != 'd'
154       || TREE_CODE (node) != FIELD_DECL)
155     return;
156
157   /* Add a 'packed' attribute.  */
158   * attributes = tree_cons (get_identifier ("packed"), NULL, * attributes);
159   
160   /* If the alignment is > 8 then add an alignment attribute as well.  */
161   if (maximum_field_alignment > 8)
162     {
163       /* If the aligned attribute is already present then do not override it.  */
164       for (a = * attributes; a; a = TREE_CHAIN (a))
165         {
166           tree name = TREE_PURPOSE (a);
167           if (strcmp (IDENTIFIER_POINTER (name), "aligned") == 0)
168             break;
169         }
170       
171       if (a == NULL)
172         for (a = * prefix; a; a = TREE_CHAIN (a))
173           {
174             tree name = TREE_PURPOSE (a);
175             if (strcmp (IDENTIFIER_POINTER (name), "aligned") == 0)
176               break;
177           }
178   
179       if (a == NULL)
180         {
181           * attributes = tree_cons
182               (get_identifier ("aligned"),
183                tree_cons (NULL,
184                           build_int_2 (maximum_field_alignment / 8, 0),
185                           NULL),
186                * attributes);
187         }
188     }
189
190   return;
191 }
192 #endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
193 \f
194 #ifdef HANDLE_PRAGMA_WEAK
195 static int add_weak PROTO((char *, char *));
196
197 static int
198 add_weak (name, value)
199      char * name;
200      char * value;
201 {
202   struct weak_syms * weak;
203
204   weak = (struct weak_syms *) permalloc (sizeof (struct weak_syms));
205
206   if (weak == NULL)
207     return 0;
208   
209   weak->next  = weak_decls;
210   weak->name  = name;
211   weak->value = value;
212   weak_decls  = weak;
213
214   return 1;
215 }
216 #endif /* HANDLE_PRAGMA_WEAK */
217 \f
218 /* Handle one token of a pragma directive.  TOKEN is the current token, and
219    STRING is its printable form.  Some front ends do not support generating
220    tokens, and will only pass in a STRING.  Also some front ends will reuse
221    the buffer containing STRING, so it must be copied to a local buffer if
222    it needs to be preserved.
223
224    If STRING is non-NULL, then the return value will be ignored, and there
225    will be futher calls to handle_pragma_token() in order to handle the rest of
226    the line containing the #pragma directive.  If STRING is NULL, the entire
227    line has now been presented to handle_pragma_token() and the return value
228    should be zero if the pragma flawed in some way, or if the pragma was not
229    recognised, and non-zero if it was successfully handled.  */
230
231 int
232 handle_pragma_token (string, token)
233      char * string;
234      tree token;
235 {
236   static enum pragma_state state = ps_start;
237   static enum pragma_state type;
238   static char * name;
239   static char * value;
240   static int align;
241
242   /* If we have reached the end of the #pragma directive then
243      determine what value we should return.  */
244   
245   if (string == NULL)
246     {
247       int ret_val = 0;
248
249       switch (type)
250         {
251         default:
252           abort ();
253           break;
254
255         case ps_done:
256           /* The pragma was not recognised.  */
257           break;
258           
259 #ifdef HANDLE_PRAGMA_PACK         
260         case ps_pack:
261           if (state == ps_right)
262             {
263               maximum_field_alignment = align * 8;
264               ret_val = 1;
265             }
266           else
267             warning ("malformed `#pragma pack'");
268           break;
269 #endif /* HANDLE_PRAGMA_PACK */
270           
271 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
272         case ps_push:
273           if (state == ps_right)
274             ret_val = push_alignment (align);
275           else
276             warning ("incomplete '#pragma pack(push,<n>)'");
277           break;
278           
279         case ps_pop:
280           if (state == ps_right)
281             ret_val = pop_alignment ();
282           else
283             warning ("missing closing parenthesis in '#pragma pack(pop)'");
284           break;
285 #endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
286           
287 #ifdef HANDLE_PRAGMA_WEAK
288         case ps_weak:
289           if (HANDLE_PRAGMA_WEAK)
290             {
291               if (state == ps_name)
292                 ret_val = add_weak (name, NULL);
293               else if (state == ps_value)
294                 ret_val = add_weak (name, value);
295               else
296                 warning ("malformed `#pragma weak'");
297             }
298           else
299             ret_val = 1; /* Ignore the pragma.  */
300           break;
301 #endif /* HANDLE_PRAGMA_WEAK */
302         }
303
304       type = state = ps_start;
305       
306       return ret_val;
307     }
308
309   /* If we have been given a token, but it is not an identifier,
310      or a small constant, then something has gone wrong.  */
311   if (token)
312     {
313       switch (TREE_CODE (token))
314         {
315         case IDENTIFIER_NODE:
316           break;
317           
318         case INTEGER_CST:
319           if (TREE_INT_CST_HIGH (token) != 0)
320             return 0;
321           break;
322           
323         default:
324           return 0;
325         }
326     }
327       
328   switch (state)
329     {
330     case ps_start:
331       type = state = ps_done;
332 #ifdef HANDLE_PRAGMA_PACK
333       if (strcmp (string, "pack") == 0)
334         type = state = ps_pack;
335 #endif
336 #ifdef HANDLE_PRAGMA_WEAK
337       if (strcmp (string, "weak") == 0)
338         type = state = ps_weak;
339 #endif    
340       break;
341       
342 #ifdef HANDLE_PRAGMA_WEAK
343     case ps_weak:
344       name = permalloc (strlen (string) + 1);
345       if (name == NULL)
346         {
347           warning ("Out of memory parsing #pragma weak");
348           state = ps_bad;
349         }
350       else
351         {
352           strcpy (name, string);
353           state = ps_name;
354         }
355       break;
356       
357     case ps_name:
358       state = (strcmp (string, "=") ? ps_bad : ps_equals);
359       break;
360
361     case ps_equals:
362       value = permalloc (strlen (string) + 1);
363       if (value == NULL)
364         {
365           warning ("Out of memory parsing #pragma weak");
366           state = ps_bad;
367         }
368       else
369         {
370           strcpy (value, string);
371           state = ps_value;
372         }
373       break;
374
375     case ps_value:
376       state = ps_bad;
377       break;
378 #endif /* HANDLE_PRAGMA_WEAK */
379       
380 #ifdef HANDLE_PRAGMA_PACK
381     case ps_pack:
382       state = (strcmp (string, "(") ? ps_bad : ps_left);
383       break;
384
385     case ps_left:
386       align = atoi (string);
387       switch (align)
388         {
389         case 1:
390         case 2:
391         case 4:
392           state = ps_align;
393           break;
394
395         case 0:
396           state = (strcmp (string, ")") ? ps_bad : ps_right);
397 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
398           if (state == ps_bad)
399             {
400               if (strcmp (string, "push") == 0)
401                 type = state = ps_push;
402               else if (strcmp (string, "pop") == 0)
403                 type = state = ps_pop;
404             }
405 #endif
406           break;
407
408         default:
409           state = ps_bad;
410           break;
411         }
412       break;
413
414 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
415     case ps_pop:
416 #endif
417     case ps_align:
418       state = (strcmp (string, ")") ? ps_bad : ps_right);
419       break;
420
421     case ps_right:
422       state = ps_bad;
423       break;
424 #endif /* HANDLE_PRAGMA_PACK */
425
426 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
427     case ps_push:
428       state = (strcmp (string, ",") ? ps_bad : ps_comma);
429       break;
430
431     case ps_comma:
432       align = atoi (string);
433       state = ps_align;
434       break;
435 #endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
436       
437     case ps_bad:
438     case ps_done:
439       break;
440
441     default:
442       abort ();
443     }
444
445   return 1;
446 }
447 #endif /* HANDLE_GENERIC_PRAGMAS */