133965Sjdp/* cond.c - conditional assembly pseudo-ops, and .include
2218822Sdim   Copyright 1990, 1991, 1992, 1993, 1995, 1997, 1998, 2000, 2001, 2002,
3218822Sdim   2003, 2006 Free Software Foundation, Inc.
433965Sjdp
533965Sjdp   This file is part of GAS, the GNU Assembler.
633965Sjdp
733965Sjdp   GAS is free software; you can redistribute it and/or modify
833965Sjdp   it under the terms of the GNU General Public License as published by
933965Sjdp   the Free Software Foundation; either version 2, or (at your option)
1033965Sjdp   any later version.
1133965Sjdp
1233965Sjdp   GAS is distributed in the hope that it will be useful,
1333965Sjdp   but WITHOUT ANY WARRANTY; without even the implied warranty of
1433965Sjdp   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1533965Sjdp   GNU General Public License for more details.
1633965Sjdp
1733965Sjdp   You should have received a copy of the GNU General Public License
1833965Sjdp   along with GAS; see the file COPYING.  If not, write to the Free
19218822Sdim   Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
20218822Sdim   02110-1301, USA.  */
2133965Sjdp
2233965Sjdp#include "as.h"
23218822Sdim#include "sb.h"
2433965Sjdp#include "macro.h"
2533965Sjdp
2633965Sjdp#include "obstack.h"
2733965Sjdp
2877298Sobrien/* This is allocated to grow and shrink as .ifdef/.endif pairs are
2977298Sobrien   scanned.  */
3033965Sjdpstruct obstack cond_obstack;
3133965Sjdp
3277298Sobrienstruct file_line {
3333965Sjdp  char *file;
3433965Sjdp  unsigned int line;
3533965Sjdp};
3633965Sjdp
3733965Sjdp/* We push one of these structures for each .if, and pop it at the
3833965Sjdp   .endif.  */
3933965Sjdp
4077298Sobrienstruct conditional_frame {
4133965Sjdp  /* The source file & line number of the "if".  */
4233965Sjdp  struct file_line if_file_line;
4333965Sjdp  /* The source file & line of the "else".  */
4433965Sjdp  struct file_line else_file_line;
4533965Sjdp  /* The previous conditional.  */
4633965Sjdp  struct conditional_frame *previous_cframe;
4733965Sjdp  /* Have we seen an else yet?  */
4833965Sjdp  int else_seen;
4933965Sjdp  /* Whether we are currently ignoring input.  */
5033965Sjdp  int ignoring;
5177298Sobrien  /* Whether a conditional at a higher level is ignoring input.
5277298Sobrien     Set also when a branch of an "if .. elseif .." tree has matched
5377298Sobrien     to prevent further matches.  */
5433965Sjdp  int dead_tree;
5533965Sjdp  /* Macro nesting level at which this conditional was created.  */
5633965Sjdp  int macro_nest;
5733965Sjdp};
5833965Sjdp
59130561Sobrienstatic void initialize_cframe (struct conditional_frame *cframe);
60130561Sobrienstatic char *get_mri_string (int, int *);
6133965Sjdp
6233965Sjdpstatic struct conditional_frame *current_cframe = NULL;
6333965Sjdp
64130561Sobrien/* Performs the .ifdef (test_defined == 1) and
65130561Sobrien   the .ifndef (test_defined == 0) pseudo op.  */
66130561Sobrien
6777298Sobrienvoid
68130561Sobriens_ifdef (int test_defined)
6933965Sjdp{
7077298Sobrien  /* Points to name of symbol.  */
71130561Sobrien  char *name;
7277298Sobrien  /* Points to symbol.  */
73130561Sobrien  symbolS *symbolP;
7433965Sjdp  struct conditional_frame cframe;
75130561Sobrien  char c;
7633965Sjdp
7777298Sobrien  /* Leading whitespace is part of operand.  */
7877298Sobrien  SKIP_WHITESPACE ();
7933965Sjdp  name = input_line_pointer;
8033965Sjdp
8133965Sjdp  if (!is_name_beginner (*name))
8233965Sjdp    {
8360484Sobrien      as_bad (_("invalid identifier for \".ifdef\""));
8433965Sjdp      obstack_1grow (&cond_obstack, 0);
8533965Sjdp      ignore_rest_of_line ();
86130561Sobrien      return;
8733965Sjdp    }
88130561Sobrien
89130561Sobrien  c = get_symbol_end ();
90130561Sobrien  symbolP = symbol_find (name);
91130561Sobrien  *input_line_pointer = c;
92130561Sobrien
93130561Sobrien  initialize_cframe (&cframe);
94130561Sobrien
95130561Sobrien  if (cframe.dead_tree)
96130561Sobrien    cframe.ignoring = 1;
9733965Sjdp  else
9833965Sjdp    {
99130561Sobrien      int is_defined;
10033965Sjdp
101130561Sobrien      /* Use the same definition of 'defined' as .equiv so that a symbol
102130561Sobrien	 which has been referenced but not yet given a value/address is
103130561Sobrien	 considered to be undefined.  */
104130561Sobrien      is_defined =
105130561Sobrien	symbolP != NULL
106218822Sdim	&& (S_IS_DEFINED (symbolP) || symbol_equated_p (symbolP))
107130561Sobrien	&& S_GET_SEGMENT (symbolP) != reg_section;
10833965Sjdp
109130561Sobrien      cframe.ignoring = ! (test_defined ^ is_defined);
110130561Sobrien    }
11133965Sjdp
112130561Sobrien  current_cframe = ((struct conditional_frame *)
113130561Sobrien		    obstack_copy (&cond_obstack, &cframe,
114130561Sobrien				  sizeof (cframe)));
11533965Sjdp
116130561Sobrien  if (LISTING_SKIP_COND ()
117130561Sobrien      && cframe.ignoring
118130561Sobrien      && (cframe.previous_cframe == NULL
119130561Sobrien	  || ! cframe.previous_cframe->ignoring))
120130561Sobrien    listing_list (2);
121130561Sobrien
122130561Sobrien  demand_empty_rest_of_line ();
12377298Sobrien}
12433965Sjdp
12577298Sobrienvoid
126130561Sobriens_if (int arg)
12733965Sjdp{
12833965Sjdp  expressionS operand;
12933965Sjdp  struct conditional_frame cframe;
13033965Sjdp  int t;
13133965Sjdp  char *stop = NULL;
13233965Sjdp  char stopc;
13333965Sjdp
13433965Sjdp  if (flag_mri)
13533965Sjdp    stop = mri_comment_field (&stopc);
13633965Sjdp
13777298Sobrien  /* Leading whitespace is part of operand.  */
13877298Sobrien  SKIP_WHITESPACE ();
13933965Sjdp
14033965Sjdp  if (current_cframe != NULL && current_cframe->ignoring)
14133965Sjdp    {
14233965Sjdp      operand.X_add_number = 0;
14333965Sjdp      while (! is_end_of_line[(unsigned char) *input_line_pointer])
14433965Sjdp	++input_line_pointer;
14533965Sjdp    }
14633965Sjdp  else
14733965Sjdp    {
148218822Sdim      expression_and_evaluate (&operand);
14933965Sjdp      if (operand.X_op != O_constant)
15060484Sobrien	as_bad (_("non-constant expression in \".if\" statement"));
15133965Sjdp    }
15233965Sjdp
15333965Sjdp  switch ((operatorT) arg)
15433965Sjdp    {
15533965Sjdp    case O_eq: t = operand.X_add_number == 0; break;
15633965Sjdp    case O_ne: t = operand.X_add_number != 0; break;
15733965Sjdp    case O_lt: t = operand.X_add_number < 0; break;
15833965Sjdp    case O_le: t = operand.X_add_number <= 0; break;
15933965Sjdp    case O_ge: t = operand.X_add_number >= 0; break;
16033965Sjdp    case O_gt: t = operand.X_add_number > 0; break;
16133965Sjdp    default:
16233965Sjdp      abort ();
16338889Sjdp      return;
16433965Sjdp    }
16533965Sjdp
16633965Sjdp  /* If the above error is signaled, this will dispatch
16733965Sjdp     using an undefined result.  No big deal.  */
16833965Sjdp  initialize_cframe (&cframe);
16933965Sjdp  cframe.ignoring = cframe.dead_tree || ! t;
17033965Sjdp  current_cframe = ((struct conditional_frame *)
17133965Sjdp		    obstack_copy (&cond_obstack, &cframe, sizeof (cframe)));
17233965Sjdp
17333965Sjdp  if (LISTING_SKIP_COND ()
17433965Sjdp      && cframe.ignoring
17533965Sjdp      && (cframe.previous_cframe == NULL
17633965Sjdp	  || ! cframe.previous_cframe->ignoring))
17733965Sjdp    listing_list (2);
17833965Sjdp
17933965Sjdp  if (flag_mri)
18033965Sjdp    mri_comment_end (stop, stopc);
18133965Sjdp
18233965Sjdp  demand_empty_rest_of_line ();
18377298Sobrien}
18433965Sjdp
185218822Sdim/* Performs the .ifb (test_blank == 1) and
186218822Sdim   the .ifnb (test_blank == 0) pseudo op.  */
187218822Sdim
188218822Sdimvoid
189218822Sdims_ifb (int test_blank)
190218822Sdim{
191218822Sdim  struct conditional_frame cframe;
192218822Sdim
193218822Sdim  initialize_cframe (&cframe);
194218822Sdim
195218822Sdim  if (cframe.dead_tree)
196218822Sdim    cframe.ignoring = 1;
197218822Sdim  else
198218822Sdim    {
199218822Sdim      int is_eol;
200218822Sdim
201218822Sdim      SKIP_WHITESPACE ();
202218822Sdim      is_eol = is_end_of_line[(unsigned char) *input_line_pointer];
203218822Sdim      cframe.ignoring = (test_blank == !is_eol);
204218822Sdim    }
205218822Sdim
206218822Sdim  current_cframe = ((struct conditional_frame *)
207218822Sdim		    obstack_copy (&cond_obstack, &cframe,
208218822Sdim				  sizeof (cframe)));
209218822Sdim
210218822Sdim  if (LISTING_SKIP_COND ()
211218822Sdim      && cframe.ignoring
212218822Sdim      && (cframe.previous_cframe == NULL
213218822Sdim	  || ! cframe.previous_cframe->ignoring))
214218822Sdim    listing_list (2);
215218822Sdim
216218822Sdim  ignore_rest_of_line ();
217218822Sdim}
218218822Sdim
21933965Sjdp/* Get a string for the MRI IFC or IFNC pseudo-ops.  */
22033965Sjdp
22133965Sjdpstatic char *
222130561Sobrienget_mri_string (int terminator, int *len)
22333965Sjdp{
22433965Sjdp  char *ret;
22533965Sjdp  char *s;
22633965Sjdp
22733965Sjdp  SKIP_WHITESPACE ();
22833965Sjdp  s = ret = input_line_pointer;
22933965Sjdp  if (*input_line_pointer == '\'')
23033965Sjdp    {
23133965Sjdp      ++s;
23233965Sjdp      ++input_line_pointer;
23333965Sjdp      while (! is_end_of_line[(unsigned char) *input_line_pointer])
23433965Sjdp	{
23533965Sjdp	  *s++ = *input_line_pointer++;
23633965Sjdp	  if (s[-1] == '\'')
23733965Sjdp	    {
23833965Sjdp	      if (*input_line_pointer != '\'')
23933965Sjdp		break;
24033965Sjdp	      ++input_line_pointer;
24133965Sjdp	    }
24233965Sjdp	}
24333965Sjdp      SKIP_WHITESPACE ();
24433965Sjdp    }
24533965Sjdp  else
24633965Sjdp    {
24733965Sjdp      while (*input_line_pointer != terminator
24833965Sjdp	     && ! is_end_of_line[(unsigned char) *input_line_pointer])
24933965Sjdp	++input_line_pointer;
25033965Sjdp      s = input_line_pointer;
25133965Sjdp      while (s > ret && (s[-1] == ' ' || s[-1] == '\t'))
25233965Sjdp	--s;
25333965Sjdp    }
25433965Sjdp
25533965Sjdp  *len = s - ret;
25633965Sjdp  return ret;
25733965Sjdp}
25833965Sjdp
25933965Sjdp/* The MRI IFC and IFNC pseudo-ops.  */
26033965Sjdp
26133965Sjdpvoid
262130561Sobriens_ifc (int arg)
26333965Sjdp{
26433965Sjdp  char *stop = NULL;
26533965Sjdp  char stopc;
26633965Sjdp  char *s1, *s2;
26733965Sjdp  int len1, len2;
26833965Sjdp  int res;
26933965Sjdp  struct conditional_frame cframe;
27033965Sjdp
27133965Sjdp  if (flag_mri)
27233965Sjdp    stop = mri_comment_field (&stopc);
27333965Sjdp
27433965Sjdp  s1 = get_mri_string (',', &len1);
27533965Sjdp
27633965Sjdp  if (*input_line_pointer != ',')
27760484Sobrien    as_bad (_("bad format for ifc or ifnc"));
27833965Sjdp  else
27933965Sjdp    ++input_line_pointer;
28033965Sjdp
28133965Sjdp  s2 = get_mri_string (';', &len2);
28233965Sjdp
28333965Sjdp  res = len1 == len2 && strncmp (s1, s2, len1) == 0;
28433965Sjdp
28533965Sjdp  initialize_cframe (&cframe);
28633965Sjdp  cframe.ignoring = cframe.dead_tree || ! (res ^ arg);
28733965Sjdp  current_cframe = ((struct conditional_frame *)
28833965Sjdp		    obstack_copy (&cond_obstack, &cframe, sizeof (cframe)));
28933965Sjdp
29033965Sjdp  if (LISTING_SKIP_COND ()
29133965Sjdp      && cframe.ignoring
29233965Sjdp      && (cframe.previous_cframe == NULL
29333965Sjdp	  || ! cframe.previous_cframe->ignoring))
29433965Sjdp    listing_list (2);
29533965Sjdp
29633965Sjdp  if (flag_mri)
29733965Sjdp    mri_comment_end (stop, stopc);
29838889Sjdp
29938889Sjdp  demand_empty_rest_of_line ();
30033965Sjdp}
30133965Sjdp
30277298Sobrienvoid
303130561Sobriens_elseif (int arg)
30433965Sjdp{
30560484Sobrien  if (current_cframe == NULL)
30660484Sobrien    {
30789857Sobrien      as_bad (_("\".elseif\" without matching \".if\""));
30860484Sobrien    }
30960484Sobrien  else if (current_cframe->else_seen)
31060484Sobrien    {
31189857Sobrien      as_bad (_("\".elseif\" after \".else\""));
31260484Sobrien      as_bad_where (current_cframe->else_file_line.file,
31360484Sobrien		    current_cframe->else_file_line.line,
31460484Sobrien		    _("here is the previous \"else\""));
31560484Sobrien      as_bad_where (current_cframe->if_file_line.file,
31660484Sobrien		    current_cframe->if_file_line.line,
31760484Sobrien		    _("here is the previous \"if\""));
31860484Sobrien    }
31960484Sobrien  else
32060484Sobrien    {
32160484Sobrien      as_where (&current_cframe->else_file_line.file,
32260484Sobrien		&current_cframe->else_file_line.line);
32360484Sobrien
32477298Sobrien      current_cframe->dead_tree |= !current_cframe->ignoring;
32577298Sobrien      current_cframe->ignoring = current_cframe->dead_tree;
32677298Sobrien    }
32760484Sobrien
32877298Sobrien  if (current_cframe == NULL || current_cframe->ignoring)
32960484Sobrien    {
33060484Sobrien      while (! is_end_of_line[(unsigned char) *input_line_pointer])
33160484Sobrien	++input_line_pointer;
33277298Sobrien
33377298Sobrien      if (current_cframe == NULL)
33477298Sobrien	return;
33560484Sobrien    }
33660484Sobrien  else
33760484Sobrien    {
33877298Sobrien      expressionS operand;
33977298Sobrien      int t;
34077298Sobrien
34177298Sobrien      /* Leading whitespace is part of operand.  */
34277298Sobrien      SKIP_WHITESPACE ();
34377298Sobrien
344218822Sdim      expression_and_evaluate (&operand);
34560484Sobrien      if (operand.X_op != O_constant)
34660484Sobrien	as_bad (_("non-constant expression in \".elseif\" statement"));
34777298Sobrien
34877298Sobrien      switch ((operatorT) arg)
34977298Sobrien	{
35077298Sobrien	case O_eq: t = operand.X_add_number == 0; break;
35177298Sobrien	case O_ne: t = operand.X_add_number != 0; break;
35277298Sobrien	case O_lt: t = operand.X_add_number < 0; break;
35377298Sobrien	case O_le: t = operand.X_add_number <= 0; break;
35477298Sobrien	case O_ge: t = operand.X_add_number >= 0; break;
35577298Sobrien	case O_gt: t = operand.X_add_number > 0; break;
35677298Sobrien	default:
35777298Sobrien	  abort ();
35877298Sobrien	  return;
35977298Sobrien	}
36077298Sobrien
36177298Sobrien      current_cframe->ignoring = current_cframe->dead_tree || ! t;
36260484Sobrien    }
36360484Sobrien
36460484Sobrien  if (LISTING_SKIP_COND ()
36560484Sobrien      && (current_cframe->previous_cframe == NULL
36660484Sobrien	  || ! current_cframe->previous_cframe->ignoring))
36777298Sobrien    {
36877298Sobrien      if (! current_cframe->ignoring)
36977298Sobrien	listing_list (1);
37077298Sobrien      else
37177298Sobrien	listing_list (2);
37277298Sobrien    }
37360484Sobrien
37460484Sobrien  demand_empty_rest_of_line ();
37560484Sobrien}
37660484Sobrien
37777298Sobrienvoid
378130561Sobriens_endif (int arg ATTRIBUTE_UNUSED)
37960484Sobrien{
38033965Sjdp  struct conditional_frame *hold;
38133965Sjdp
38233965Sjdp  if (current_cframe == NULL)
38333965Sjdp    {
38460484Sobrien      as_bad (_("\".endif\" without \".if\""));
38533965Sjdp    }
38633965Sjdp  else
38733965Sjdp    {
38833965Sjdp      if (LISTING_SKIP_COND ()
38933965Sjdp	  && current_cframe->ignoring
39033965Sjdp	  && (current_cframe->previous_cframe == NULL
39133965Sjdp	      || ! current_cframe->previous_cframe->ignoring))
39233965Sjdp	listing_list (1);
39333965Sjdp
39433965Sjdp      hold = current_cframe;
39533965Sjdp      current_cframe = current_cframe->previous_cframe;
39633965Sjdp      obstack_free (&cond_obstack, hold);
39733965Sjdp    }				/* if one pop too many */
39833965Sjdp
39933965Sjdp  if (flag_mri)
40033965Sjdp    {
40133965Sjdp      while (! is_end_of_line[(unsigned char) *input_line_pointer])
40233965Sjdp	++input_line_pointer;
40333965Sjdp    }
40433965Sjdp
40533965Sjdp  demand_empty_rest_of_line ();
40677298Sobrien}
40733965Sjdp
40877298Sobrienvoid
409130561Sobriens_else (int arg ATTRIBUTE_UNUSED)
41033965Sjdp{
41133965Sjdp  if (current_cframe == NULL)
41233965Sjdp    {
41389857Sobrien      as_bad (_("\".else\" without matching \".if\""));
41433965Sjdp    }
41533965Sjdp  else if (current_cframe->else_seen)
41633965Sjdp    {
41789857Sobrien      as_bad (_("duplicate \"else\""));
41833965Sjdp      as_bad_where (current_cframe->else_file_line.file,
41933965Sjdp		    current_cframe->else_file_line.line,
42060484Sobrien		    _("here is the previous \"else\""));
42133965Sjdp      as_bad_where (current_cframe->if_file_line.file,
42233965Sjdp		    current_cframe->if_file_line.line,
42360484Sobrien		    _("here is the previous \"if\""));
42433965Sjdp    }
42533965Sjdp  else
42633965Sjdp    {
42733965Sjdp      as_where (&current_cframe->else_file_line.file,
42833965Sjdp		&current_cframe->else_file_line.line);
42933965Sjdp
43077298Sobrien      current_cframe->ignoring =
43177298Sobrien	current_cframe->dead_tree | !current_cframe->ignoring;
43277298Sobrien
43377298Sobrien      if (LISTING_SKIP_COND ()
43477298Sobrien	  && (current_cframe->previous_cframe == NULL
43577298Sobrien	      || ! current_cframe->previous_cframe->ignoring))
43633965Sjdp	{
43777298Sobrien	  if (! current_cframe->ignoring)
43877298Sobrien	    listing_list (1);
43977298Sobrien	  else
44077298Sobrien	    listing_list (2);
44177298Sobrien	}
44233965Sjdp
44333965Sjdp      current_cframe->else_seen = 1;
44477298Sobrien    }
44533965Sjdp
44633965Sjdp  if (flag_mri)
44733965Sjdp    {
44833965Sjdp      while (! is_end_of_line[(unsigned char) *input_line_pointer])
44933965Sjdp	++input_line_pointer;
45033965Sjdp    }
45133965Sjdp
45233965Sjdp  demand_empty_rest_of_line ();
45377298Sobrien}
45433965Sjdp
45577298Sobrienvoid
456130561Sobriens_ifeqs (int arg)
45733965Sjdp{
45833965Sjdp  char *s1, *s2;
45933965Sjdp  int len1, len2;
46033965Sjdp  int res;
46133965Sjdp  struct conditional_frame cframe;
46233965Sjdp
46333965Sjdp  s1 = demand_copy_C_string (&len1);
46433965Sjdp
46533965Sjdp  SKIP_WHITESPACE ();
46633965Sjdp  if (*input_line_pointer != ',')
46733965Sjdp    {
46860484Sobrien      as_bad (_(".ifeqs syntax error"));
46933965Sjdp      ignore_rest_of_line ();
47033965Sjdp      return;
47133965Sjdp    }
47233965Sjdp
47333965Sjdp  ++input_line_pointer;
47433965Sjdp
47533965Sjdp  s2 = demand_copy_C_string (&len2);
47633965Sjdp
47733965Sjdp  res = len1 == len2 && strncmp (s1, s2, len1) == 0;
47833965Sjdp
47933965Sjdp  initialize_cframe (&cframe);
48033965Sjdp  cframe.ignoring = cframe.dead_tree || ! (res ^ arg);
48133965Sjdp  current_cframe = ((struct conditional_frame *)
48233965Sjdp		    obstack_copy (&cond_obstack, &cframe, sizeof (cframe)));
48333965Sjdp
48433965Sjdp  if (LISTING_SKIP_COND ()
48533965Sjdp      && cframe.ignoring
48633965Sjdp      && (cframe.previous_cframe == NULL
48733965Sjdp	  || ! cframe.previous_cframe->ignoring))
48833965Sjdp    listing_list (2);
48933965Sjdp
49033965Sjdp  demand_empty_rest_of_line ();
49177298Sobrien}
49233965Sjdp
49377298Sobrienint
494130561Sobrienignore_input (void)
49533965Sjdp{
49633965Sjdp  char *s;
49733965Sjdp
49833965Sjdp  s = input_line_pointer;
49933965Sjdp
50060484Sobrien  if (NO_PSEUDO_DOT || flag_m68k_mri)
50133965Sjdp    {
50233965Sjdp      if (s[-1] != '.')
50333965Sjdp	--s;
50433965Sjdp    }
50533965Sjdp  else
50633965Sjdp    {
50733965Sjdp      if (s[-1] != '.')
50833965Sjdp	return (current_cframe != NULL) && (current_cframe->ignoring);
50933965Sjdp    }
51033965Sjdp
51133965Sjdp  /* We cannot ignore certain pseudo ops.  */
51233965Sjdp  if (((s[0] == 'i'
51333965Sjdp	|| s[0] == 'I')
51433965Sjdp       && (!strncasecmp (s, "if", 2)
51533965Sjdp	   || !strncasecmp (s, "ifdef", 5)
51633965Sjdp	   || !strncasecmp (s, "ifndef", 6)))
51733965Sjdp      || ((s[0] == 'e'
51833965Sjdp	   || s[0] == 'E')
51933965Sjdp	  && (!strncasecmp (s, "else", 4)
52033965Sjdp	      || !strncasecmp (s, "endif", 5)
52133965Sjdp	      || !strncasecmp (s, "endc", 4))))
52233965Sjdp    return 0;
52333965Sjdp
52433965Sjdp  return (current_cframe != NULL) && (current_cframe->ignoring);
52577298Sobrien}
52633965Sjdp
52777298Sobrienstatic void
528130561Sobrieninitialize_cframe (struct conditional_frame *cframe)
52933965Sjdp{
53033965Sjdp  memset (cframe, 0, sizeof (*cframe));
53133965Sjdp  as_where (&cframe->if_file_line.file,
53233965Sjdp	    &cframe->if_file_line.line);
53333965Sjdp  cframe->previous_cframe = current_cframe;
53433965Sjdp  cframe->dead_tree = current_cframe != NULL && current_cframe->ignoring;
53533965Sjdp  cframe->macro_nest = macro_nest;
53633965Sjdp}
53733965Sjdp
53833965Sjdp/* Give an error if a conditional is unterminated inside a macro or
53933965Sjdp   the assembly as a whole.  If NEST is non negative, we are being
54033965Sjdp   called because of the end of a macro expansion.  If NEST is
54133965Sjdp   negative, we are being called at the of the input files.  */
54233965Sjdp
54333965Sjdpvoid
544130561Sobriencond_finish_check (int nest)
54533965Sjdp{
54633965Sjdp  if (current_cframe != NULL && current_cframe->macro_nest >= nest)
54733965Sjdp    {
54860484Sobrien      if (nest >= 0)
54960484Sobrien	as_bad (_("end of macro inside conditional"));
55060484Sobrien      else
55160484Sobrien	as_bad (_("end of file inside conditional"));
55233965Sjdp      as_bad_where (current_cframe->if_file_line.file,
55333965Sjdp		    current_cframe->if_file_line.line,
55460484Sobrien		    _("here is the start of the unterminated conditional"));
55533965Sjdp      if (current_cframe->else_seen)
55633965Sjdp	as_bad_where (current_cframe->else_file_line.file,
55733965Sjdp		      current_cframe->else_file_line.line,
55860484Sobrien		      _("here is the \"else\" of the unterminated conditional"));
55933965Sjdp    }
56033965Sjdp}
56133965Sjdp
56233965Sjdp/* This function is called when we exit out of a macro.  We assume
56333965Sjdp   that any conditionals which began within the macro are correctly
56433965Sjdp   nested, and just pop them off the stack.  */
56533965Sjdp
56633965Sjdpvoid
567130561Sobriencond_exit_macro (int nest)
56833965Sjdp{
56933965Sjdp  while (current_cframe != NULL && current_cframe->macro_nest >= nest)
57033965Sjdp    {
57133965Sjdp      struct conditional_frame *hold;
57233965Sjdp
57333965Sjdp      hold = current_cframe;
57433965Sjdp      current_cframe = current_cframe->previous_cframe;
57533965Sjdp      obstack_free (&cond_obstack, hold);
57633965Sjdp    }
57733965Sjdp}
578