OSDN Git Service

H
[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       || alignment_stack == NULL)
151     return;
152
153   /* We are only interested in fields.  */
154   if (TREE_CODE_CLASS (TREE_CODE (node)) != 'd'
155       || TREE_CODE (node) != FIELD_DECL)
156     return;
157
158   /* Add a 'packed' attribute.  */
159   * attributes = tree_cons (get_identifier ("packed"), NULL, * attributes);
160   
161   /* If the alignment is > 8 then add an alignment attribute as well.  */
162   if (maximum_field_alignment > 8)
163     {
164       /* If the aligned attribute is already present then do not override it.  */
165       for (a = * attributes; a; a = TREE_CHAIN (a))
166         {
167           tree name = TREE_PURPOSE (a);
168           if (strcmp (IDENTIFIER_POINTER (name), "aligned") == 0)
169             break;
170         }
171       
172       if (a == NULL)
173         for (a = * prefix; a; a = TREE_CHAIN (a))
174           {
175             tree name = TREE_PURPOSE (a);
176             if (strcmp (IDENTIFIER_POINTER (name), "aligned") == 0)
177               break;
178           }
179   
180       if (a == NULL)
181         {
182           * attributes = tree_cons
183               (get_identifier ("aligned"),
184                tree_cons (NULL,
185                           build_int_2 (maximum_field_alignment / 8, 0),
186                           NULL),
187                * attributes);
188         }
189     }
190
191   return;
192 }
193 #endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
194 \f
195 #ifdef HANDLE_PRAGMA_WEAK
196 static int add_weak PROTO((char *, char *));
197
198 static int
199 add_weak (name, value)
200      char * name;
201      char * value;
202 {
203   struct weak_syms * weak;
204
205   weak = (struct weak_syms *) permalloc (sizeof (struct weak_syms));
206
207   if (weak == NULL)
208     return 0;
209   
210   weak->next  = weak_decls;
211   weak->name  = name;
212   weak->value = value;
213   weak_decls  = weak;
214
215   return 1;
216 }
217 #endif /* HANDLE_PRAGMA_WEAK */
218 \f
219 /* Handle one token of a pragma directive.  TOKEN is the current token, and
220    STRING is its printable form.  Some front ends do not support generating
221    tokens, and will only pass in a STRING.  Also some front ends will reuse
222    the buffer containing STRING, so it must be copied to a local buffer if
223    it needs to be preserved.
224
225    If STRING is non-NULL, then the return value will be ignored, and there
226    will be futher calls to handle_pragma_token() in order to handle the rest of
227    the line containing the #pragma directive.  If STRING is NULL, the entire
228    line has now been presented to handle_pragma_token() and the return value
229    should be zero if the pragma flawed in some way, or if the pragma was not
230    recognised, and non-zero if it was successfully handled.  */
231
232 int
233 handle_pragma_token (string, token)
234      char * string;
235      tree token;
236 {
237   static enum pragma_state state = ps_start;
238   static enum pragma_state type;
239   static char * name;
240   static char * value;
241   static int align;
242
243   /* If we have reached the end of the #pragma directive then
244      determine what value we should return.  */
245   
246   if (string == NULL)
247     {
248       int ret_val = 0;
249
250       switch (type)
251         {
252         default:
253           abort ();
254           break;
255
256         case ps_done:
257           /* The pragma was not recognised.  */
258           break;
259           
260 #ifdef HANDLE_PRAGMA_PACK         
261         case ps_pack:
262           if (state == ps_right)
263             {
264               maximum_field_alignment = align * 8;
265               ret_val = 1;
266             }
267           else
268             warning ("malformed `#pragma pack'");
269           break;
270 #endif /* HANDLE_PRAGMA_PACK */
271           
272 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
273         case ps_push:
274           if (state == ps_right)
275             ret_val = push_alignment (align);
276           else
277             warning ("incomplete '#pragma pack(push,<n>)'");
278           break;
279           
280         case ps_pop:
281           if (state == ps_right)
282             ret_val = pop_alignment ();
283           else
284             warning ("missing closing parenthesis in '#pragma pack(pop)'");
285           break;
286 #endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
287           
288 #ifdef HANDLE_PRAGMA_WEAK
289         case ps_weak:
290           if (HANDLE_PRAGMA_WEAK)
291             {
292               if (state == ps_name)
293                 ret_val = add_weak (name, NULL);
294               else if (state == ps_value)
295                 ret_val = add_weak (name, value);
296               else
297                 warning ("malformed `#pragma weak'");
298             }
299           else
300             ret_val = 1; /* Ignore the pragma.  */
301           break;
302 #endif /* HANDLE_PRAGMA_WEAK */
303         }
304
305       type = state = ps_start;
306       
307       return ret_val;
308     }
309
310   /* If we have been given a token, but it is not an identifier,
311      or a small constant, then something has gone wrong.  */
312   if (token)
313     {
314       switch (TREE_CODE (token))
315         {
316         case IDENTIFIER_NODE:
317           break;
318           
319         case INTEGER_CST:
320           if (TREE_INT_CST_HIGH (token) != 0)
321             return 0;
322           break;
323           
324         default:
325           return 0;
326         }
327     }
328       
329   switch (state)
330     {
331     case ps_start:
332       type = state = ps_done;
333 #ifdef HANDLE_PRAGMA_PACK
334       if (strcmp (string, "pack") == 0)
335         type = state = ps_pack;
336 #endif
337 #ifdef HANDLE_PRAGMA_WEAK
338       if (strcmp (string, "weak") == 0)
339         type = state = ps_weak;
340 #endif    
341       break;
342       
343 #ifdef HANDLE_PRAGMA_WEAK
344     case ps_weak:
345       name = permalloc (strlen (string) + 1);
346       if (name == NULL)
347         {
348           warning ("Out of memory parsing #pragma weak");
349           state = ps_bad;
350         }
351       else
352         {
353           strcpy (name, string);
354           state = ps_name;
355         }
356       break;
357       
358     case ps_name:
359       state = (strcmp (string, "=") ? ps_bad : ps_equals);
360       break;
361
362     case ps_equals:
363       value = permalloc (strlen (string) + 1);
364       if (value == NULL)
365         {
366           warning ("Out of memory parsing #pragma weak");
367           state = ps_bad;
368         }
369       else
370         {
371           strcpy (value, string);
372           state = ps_value;
373         }
374       break;
375
376     case ps_value:
377       state = ps_bad;
378       break;
379 #endif /* HANDLE_PRAGMA_WEAK */
380       
381 #ifdef HANDLE_PRAGMA_PACK
382     case ps_pack:
383       state = (strcmp (string, "(") ? ps_bad : ps_left);
384       break;
385
386     case ps_left:
387
388       if (token && TREE_CODE(token) == INTEGER_CST) 
389         align = TREE_INT_CST_LOW(token);
390       else
391         align = atoi (string);
392       switch (align)
393         {
394         case 1:
395         case 2:
396         case 4:
397           state = ps_align;
398           break;
399
400         case 0:
401           state = (strcmp (string, ")") ? ps_bad : ps_right);
402 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
403           if (state == ps_bad)
404             {
405               if (strcmp (string, "push") == 0)
406                 type = state = ps_push;
407               else if (strcmp (string, "pop") == 0)
408                 type = state = ps_pop;
409             }
410 #endif
411           break;
412
413         default:
414           state = ps_bad;
415           break;
416         }
417       break;
418
419 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
420     case ps_pop:
421 #endif
422     case ps_align:
423       state = (strcmp (string, ")") ? ps_bad : ps_right);
424       break;
425
426     case ps_right:
427       state = ps_bad;
428       break;
429 #endif /* HANDLE_PRAGMA_PACK */
430
431 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
432     case ps_push:
433       state = (strcmp (string, ",") ? ps_bad : ps_comma);
434       break;
435
436     case ps_comma:
437       align = atoi (string);
438       state = ps_align;
439       break;
440 #endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
441       
442     case ps_bad:
443     case ps_done:
444       break;
445
446     default:
447       abort ();
448     }
449
450   return 1;
451 }
452 #endif /* HANDLE_GENERIC_PRAGMAS */