xref: /dflybsd-src/contrib/binutils-2.34/gas/cond.c (revision b52ef7118d1621abed722c5bbbd542210290ecef)
1*fae548d3Szrj /* cond.c - conditional assembly pseudo-ops, and .include
2*fae548d3Szrj    Copyright (C) 1990-2020 Free Software Foundation, Inc.
3*fae548d3Szrj 
4*fae548d3Szrj    This file is part of GAS, the GNU Assembler.
5*fae548d3Szrj 
6*fae548d3Szrj    GAS is free software; you can redistribute it and/or modify
7*fae548d3Szrj    it under the terms of the GNU General Public License as published by
8*fae548d3Szrj    the Free Software Foundation; either version 3, or (at your option)
9*fae548d3Szrj    any later version.
10*fae548d3Szrj 
11*fae548d3Szrj    GAS is distributed in the hope that it will be useful,
12*fae548d3Szrj    but WITHOUT ANY WARRANTY; without even the implied warranty of
13*fae548d3Szrj    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14*fae548d3Szrj    GNU General Public License for more details.
15*fae548d3Szrj 
16*fae548d3Szrj    You should have received a copy of the GNU General Public License
17*fae548d3Szrj    along with GAS; see the file COPYING.  If not, write to the Free
18*fae548d3Szrj    Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
19*fae548d3Szrj    02110-1301, USA.  */
20*fae548d3Szrj 
21*fae548d3Szrj #include "as.h"
22*fae548d3Szrj #include "sb.h"
23*fae548d3Szrj #include "macro.h"
24*fae548d3Szrj 
25*fae548d3Szrj #include "obstack.h"
26*fae548d3Szrj 
27*fae548d3Szrj /* This is allocated to grow and shrink as .ifdef/.endif pairs are
28*fae548d3Szrj    scanned.  */
29*fae548d3Szrj struct obstack cond_obstack;
30*fae548d3Szrj 
31*fae548d3Szrj struct file_line
32*fae548d3Szrj {
33*fae548d3Szrj   const char *file;
34*fae548d3Szrj   unsigned int line;
35*fae548d3Szrj };
36*fae548d3Szrj 
37*fae548d3Szrj /* We push one of these structures for each .if, and pop it at the
38*fae548d3Szrj    .endif.  */
39*fae548d3Szrj 
40*fae548d3Szrj struct conditional_frame
41*fae548d3Szrj {
42*fae548d3Szrj   /* The source file & line number of the "if".  */
43*fae548d3Szrj   struct file_line if_file_line;
44*fae548d3Szrj   /* The source file & line of the "else".  */
45*fae548d3Szrj   struct file_line else_file_line;
46*fae548d3Szrj   /* The previous conditional.  */
47*fae548d3Szrj   struct conditional_frame *previous_cframe;
48*fae548d3Szrj   /* Have we seen an else yet?  */
49*fae548d3Szrj   int else_seen;
50*fae548d3Szrj   /* Whether we are currently ignoring input.  */
51*fae548d3Szrj   int ignoring;
52*fae548d3Szrj   /* Whether a conditional at a higher level is ignoring input.
53*fae548d3Szrj      Set also when a branch of an "if .. elseif .." tree has matched
54*fae548d3Szrj      to prevent further matches.  */
55*fae548d3Szrj   int dead_tree;
56*fae548d3Szrj   /* Macro nesting level at which this conditional was created.  */
57*fae548d3Szrj   int macro_nest;
58*fae548d3Szrj };
59*fae548d3Szrj 
60*fae548d3Szrj static void initialize_cframe (struct conditional_frame *cframe);
61*fae548d3Szrj static char *get_mri_string (int, int *);
62*fae548d3Szrj 
63*fae548d3Szrj static struct conditional_frame *current_cframe = NULL;
64*fae548d3Szrj 
65*fae548d3Szrj /* Performs the .ifdef (test_defined == 1) and
66*fae548d3Szrj    the .ifndef (test_defined == 0) pseudo op.  */
67*fae548d3Szrj 
68*fae548d3Szrj void
s_ifdef(int test_defined)69*fae548d3Szrj s_ifdef (int test_defined)
70*fae548d3Szrj {
71*fae548d3Szrj   /* Points to name of symbol.  */
72*fae548d3Szrj   char *name;
73*fae548d3Szrj   /* Points to symbol.  */
74*fae548d3Szrj   symbolS *symbolP;
75*fae548d3Szrj   struct conditional_frame cframe;
76*fae548d3Szrj   char c;
77*fae548d3Szrj 
78*fae548d3Szrj   /* Leading whitespace is part of operand.  */
79*fae548d3Szrj   SKIP_WHITESPACE ();
80*fae548d3Szrj   name = input_line_pointer;
81*fae548d3Szrj 
82*fae548d3Szrj   if (!is_name_beginner (*name) && *name != '"')
83*fae548d3Szrj     {
84*fae548d3Szrj       as_bad (_("invalid identifier for \".ifdef\""));
85*fae548d3Szrj       obstack_1grow (&cond_obstack, 0);
86*fae548d3Szrj       ignore_rest_of_line ();
87*fae548d3Szrj       return;
88*fae548d3Szrj     }
89*fae548d3Szrj 
90*fae548d3Szrj   c = get_symbol_name (& name);
91*fae548d3Szrj   symbolP = symbol_find (name);
92*fae548d3Szrj   (void) restore_line_pointer (c);
93*fae548d3Szrj 
94*fae548d3Szrj   initialize_cframe (&cframe);
95*fae548d3Szrj 
96*fae548d3Szrj   if (cframe.dead_tree)
97*fae548d3Szrj     cframe.ignoring = 1;
98*fae548d3Szrj   else
99*fae548d3Szrj     {
100*fae548d3Szrj       int is_defined;
101*fae548d3Szrj 
102*fae548d3Szrj       /* Use the same definition of 'defined' as .equiv so that a symbol
103*fae548d3Szrj 	 which has been referenced but not yet given a value/address is
104*fae548d3Szrj 	 considered to be undefined.  */
105*fae548d3Szrj       is_defined =
106*fae548d3Szrj 	symbolP != NULL
107*fae548d3Szrj 	&& (S_IS_DEFINED (symbolP) || symbol_equated_p (symbolP))
108*fae548d3Szrj 	&& S_GET_SEGMENT (symbolP) != reg_section;
109*fae548d3Szrj 
110*fae548d3Szrj       cframe.ignoring = ! (test_defined ^ is_defined);
111*fae548d3Szrj     }
112*fae548d3Szrj 
113*fae548d3Szrj   current_cframe =
114*fae548d3Szrj     (struct conditional_frame *) obstack_alloc (&cond_obstack, sizeof cframe);
115*fae548d3Szrj   memcpy (current_cframe, &cframe, sizeof cframe);
116*fae548d3Szrj 
117*fae548d3Szrj   if (LISTING_SKIP_COND ()
118*fae548d3Szrj       && cframe.ignoring
119*fae548d3Szrj       && (cframe.previous_cframe == NULL
120*fae548d3Szrj 	  || ! cframe.previous_cframe->ignoring))
121*fae548d3Szrj     listing_list (2);
122*fae548d3Szrj 
123*fae548d3Szrj   demand_empty_rest_of_line ();
124*fae548d3Szrj }
125*fae548d3Szrj 
126*fae548d3Szrj void
s_if(int arg)127*fae548d3Szrj s_if (int arg)
128*fae548d3Szrj {
129*fae548d3Szrj   expressionS operand;
130*fae548d3Szrj   struct conditional_frame cframe;
131*fae548d3Szrj   int t;
132*fae548d3Szrj   char *stop = NULL;
133*fae548d3Szrj   char stopc = 0;
134*fae548d3Szrj 
135*fae548d3Szrj   if (flag_mri)
136*fae548d3Szrj     stop = mri_comment_field (&stopc);
137*fae548d3Szrj 
138*fae548d3Szrj   /* Leading whitespace is part of operand.  */
139*fae548d3Szrj   SKIP_WHITESPACE ();
140*fae548d3Szrj 
141*fae548d3Szrj   if (current_cframe != NULL && current_cframe->ignoring)
142*fae548d3Szrj     {
143*fae548d3Szrj       operand.X_add_number = 0;
144*fae548d3Szrj       while (! is_end_of_line[(unsigned char) *input_line_pointer])
145*fae548d3Szrj 	++input_line_pointer;
146*fae548d3Szrj     }
147*fae548d3Szrj   else
148*fae548d3Szrj     {
149*fae548d3Szrj       expression_and_evaluate (&operand);
150*fae548d3Szrj       if (operand.X_op != O_constant)
151*fae548d3Szrj 	as_bad (_("non-constant expression in \".if\" statement"));
152*fae548d3Szrj     }
153*fae548d3Szrj 
154*fae548d3Szrj   switch ((operatorT) arg)
155*fae548d3Szrj     {
156*fae548d3Szrj     case O_eq: t = operand.X_add_number == 0; break;
157*fae548d3Szrj     case O_ne: t = operand.X_add_number != 0; break;
158*fae548d3Szrj     case O_lt: t = operand.X_add_number < 0; break;
159*fae548d3Szrj     case O_le: t = operand.X_add_number <= 0; break;
160*fae548d3Szrj     case O_ge: t = operand.X_add_number >= 0; break;
161*fae548d3Szrj     case O_gt: t = operand.X_add_number > 0; break;
162*fae548d3Szrj     default:
163*fae548d3Szrj       abort ();
164*fae548d3Szrj       return;
165*fae548d3Szrj     }
166*fae548d3Szrj 
167*fae548d3Szrj   /* If the above error is signaled, this will dispatch
168*fae548d3Szrj      using an undefined result.  No big deal.  */
169*fae548d3Szrj   initialize_cframe (&cframe);
170*fae548d3Szrj   cframe.ignoring = cframe.dead_tree || ! t;
171*fae548d3Szrj   current_cframe =
172*fae548d3Szrj     (struct conditional_frame *) obstack_alloc (&cond_obstack, sizeof cframe);
173*fae548d3Szrj   memcpy (current_cframe, & cframe, sizeof cframe);
174*fae548d3Szrj 
175*fae548d3Szrj   if (LISTING_SKIP_COND ()
176*fae548d3Szrj       && cframe.ignoring
177*fae548d3Szrj       && (cframe.previous_cframe == NULL
178*fae548d3Szrj 	  || ! cframe.previous_cframe->ignoring))
179*fae548d3Szrj     listing_list (2);
180*fae548d3Szrj 
181*fae548d3Szrj   if (flag_mri)
182*fae548d3Szrj     mri_comment_end (stop, stopc);
183*fae548d3Szrj 
184*fae548d3Szrj   demand_empty_rest_of_line ();
185*fae548d3Szrj }
186*fae548d3Szrj 
187*fae548d3Szrj /* Performs the .ifb (test_blank == 1) and
188*fae548d3Szrj    the .ifnb (test_blank == 0) pseudo op.  */
189*fae548d3Szrj 
190*fae548d3Szrj void
s_ifb(int test_blank)191*fae548d3Szrj s_ifb (int test_blank)
192*fae548d3Szrj {
193*fae548d3Szrj   struct conditional_frame cframe;
194*fae548d3Szrj 
195*fae548d3Szrj   initialize_cframe (&cframe);
196*fae548d3Szrj 
197*fae548d3Szrj   if (cframe.dead_tree)
198*fae548d3Szrj     cframe.ignoring = 1;
199*fae548d3Szrj   else
200*fae548d3Szrj     {
201*fae548d3Szrj       int is_eol;
202*fae548d3Szrj 
203*fae548d3Szrj       SKIP_WHITESPACE ();
204*fae548d3Szrj       is_eol = is_end_of_line[(unsigned char) *input_line_pointer];
205*fae548d3Szrj       cframe.ignoring = (test_blank == !is_eol);
206*fae548d3Szrj     }
207*fae548d3Szrj 
208*fae548d3Szrj   current_cframe =
209*fae548d3Szrj     (struct conditional_frame *) obstack_alloc (&cond_obstack, sizeof cframe);
210*fae548d3Szrj   memcpy (current_cframe, &cframe, sizeof cframe);
211*fae548d3Szrj 
212*fae548d3Szrj   if (LISTING_SKIP_COND ()
213*fae548d3Szrj       && cframe.ignoring
214*fae548d3Szrj       && (cframe.previous_cframe == NULL
215*fae548d3Szrj 	  || ! cframe.previous_cframe->ignoring))
216*fae548d3Szrj     listing_list (2);
217*fae548d3Szrj 
218*fae548d3Szrj   ignore_rest_of_line ();
219*fae548d3Szrj }
220*fae548d3Szrj 
221*fae548d3Szrj /* Get a string for the MRI IFC or IFNC pseudo-ops.  */
222*fae548d3Szrj 
223*fae548d3Szrj static char *
get_mri_string(int terminator,int * len)224*fae548d3Szrj get_mri_string (int terminator, int *len)
225*fae548d3Szrj {
226*fae548d3Szrj   char *ret;
227*fae548d3Szrj   char *s;
228*fae548d3Szrj 
229*fae548d3Szrj   SKIP_WHITESPACE ();
230*fae548d3Szrj   s = ret = input_line_pointer;
231*fae548d3Szrj   if (*input_line_pointer == '\'')
232*fae548d3Szrj     {
233*fae548d3Szrj       ++s;
234*fae548d3Szrj       ++input_line_pointer;
235*fae548d3Szrj       while (! is_end_of_line[(unsigned char) *input_line_pointer])
236*fae548d3Szrj 	{
237*fae548d3Szrj 	  *s++ = *input_line_pointer++;
238*fae548d3Szrj 	  if (s[-1] == '\'')
239*fae548d3Szrj 	    {
240*fae548d3Szrj 	      if (*input_line_pointer != '\'')
241*fae548d3Szrj 		break;
242*fae548d3Szrj 	      ++input_line_pointer;
243*fae548d3Szrj 	    }
244*fae548d3Szrj 	}
245*fae548d3Szrj       SKIP_WHITESPACE ();
246*fae548d3Szrj     }
247*fae548d3Szrj   else
248*fae548d3Szrj     {
249*fae548d3Szrj       while (*input_line_pointer != terminator
250*fae548d3Szrj 	     && ! is_end_of_line[(unsigned char) *input_line_pointer])
251*fae548d3Szrj 	++input_line_pointer;
252*fae548d3Szrj       s = input_line_pointer;
253*fae548d3Szrj       while (s > ret && (s[-1] == ' ' || s[-1] == '\t'))
254*fae548d3Szrj 	--s;
255*fae548d3Szrj     }
256*fae548d3Szrj 
257*fae548d3Szrj   *len = s - ret;
258*fae548d3Szrj   return ret;
259*fae548d3Szrj }
260*fae548d3Szrj 
261*fae548d3Szrj /* The MRI IFC and IFNC pseudo-ops.  */
262*fae548d3Szrj 
263*fae548d3Szrj void
s_ifc(int arg)264*fae548d3Szrj s_ifc (int arg)
265*fae548d3Szrj {
266*fae548d3Szrj   char *stop = NULL;
267*fae548d3Szrj   char stopc = 0;
268*fae548d3Szrj   char *s1, *s2;
269*fae548d3Szrj   int len1, len2;
270*fae548d3Szrj   int res;
271*fae548d3Szrj   struct conditional_frame cframe;
272*fae548d3Szrj 
273*fae548d3Szrj   if (flag_mri)
274*fae548d3Szrj     stop = mri_comment_field (&stopc);
275*fae548d3Szrj 
276*fae548d3Szrj   s1 = get_mri_string (',', &len1);
277*fae548d3Szrj 
278*fae548d3Szrj   if (*input_line_pointer != ',')
279*fae548d3Szrj     as_bad (_("bad format for ifc or ifnc"));
280*fae548d3Szrj   else
281*fae548d3Szrj     ++input_line_pointer;
282*fae548d3Szrj 
283*fae548d3Szrj   s2 = get_mri_string (';', &len2);
284*fae548d3Szrj 
285*fae548d3Szrj   res = len1 == len2 && strncmp (s1, s2, len1) == 0;
286*fae548d3Szrj 
287*fae548d3Szrj   initialize_cframe (&cframe);
288*fae548d3Szrj   cframe.ignoring = cframe.dead_tree || ! (res ^ arg);
289*fae548d3Szrj   current_cframe =
290*fae548d3Szrj     (struct conditional_frame *) obstack_alloc (&cond_obstack, sizeof cframe);
291*fae548d3Szrj   memcpy (current_cframe, &cframe, sizeof cframe);
292*fae548d3Szrj 
293*fae548d3Szrj  if (LISTING_SKIP_COND ()
294*fae548d3Szrj       && cframe.ignoring
295*fae548d3Szrj       && (cframe.previous_cframe == NULL
296*fae548d3Szrj 	  || ! cframe.previous_cframe->ignoring))
297*fae548d3Szrj     listing_list (2);
298*fae548d3Szrj 
299*fae548d3Szrj   if (flag_mri)
300*fae548d3Szrj     mri_comment_end (stop, stopc);
301*fae548d3Szrj 
302*fae548d3Szrj   demand_empty_rest_of_line ();
303*fae548d3Szrj }
304*fae548d3Szrj 
305*fae548d3Szrj void
s_elseif(int arg)306*fae548d3Szrj s_elseif (int arg)
307*fae548d3Szrj {
308*fae548d3Szrj   if (current_cframe == NULL)
309*fae548d3Szrj     {
310*fae548d3Szrj       as_bad (_("\".elseif\" without matching \".if\""));
311*fae548d3Szrj     }
312*fae548d3Szrj   else if (current_cframe->else_seen)
313*fae548d3Szrj     {
314*fae548d3Szrj       as_bad (_("\".elseif\" after \".else\""));
315*fae548d3Szrj       as_bad_where (current_cframe->else_file_line.file,
316*fae548d3Szrj 		    current_cframe->else_file_line.line,
317*fae548d3Szrj 		    _("here is the previous \".else\""));
318*fae548d3Szrj       as_bad_where (current_cframe->if_file_line.file,
319*fae548d3Szrj 		    current_cframe->if_file_line.line,
320*fae548d3Szrj 		    _("here is the previous \".if\""));
321*fae548d3Szrj     }
322*fae548d3Szrj   else
323*fae548d3Szrj     {
324*fae548d3Szrj       current_cframe->else_file_line.file
325*fae548d3Szrj        	= as_where (&current_cframe->else_file_line.line);
326*fae548d3Szrj 
327*fae548d3Szrj       current_cframe->dead_tree |= !current_cframe->ignoring;
328*fae548d3Szrj       current_cframe->ignoring = current_cframe->dead_tree;
329*fae548d3Szrj     }
330*fae548d3Szrj 
331*fae548d3Szrj   if (current_cframe == NULL || current_cframe->ignoring)
332*fae548d3Szrj     {
333*fae548d3Szrj       while (! is_end_of_line[(unsigned char) *input_line_pointer])
334*fae548d3Szrj 	++input_line_pointer;
335*fae548d3Szrj 
336*fae548d3Szrj       if (current_cframe == NULL)
337*fae548d3Szrj 	return;
338*fae548d3Szrj     }
339*fae548d3Szrj   else
340*fae548d3Szrj     {
341*fae548d3Szrj       expressionS operand;
342*fae548d3Szrj       int t;
343*fae548d3Szrj 
344*fae548d3Szrj       /* Leading whitespace is part of operand.  */
345*fae548d3Szrj       SKIP_WHITESPACE ();
346*fae548d3Szrj 
347*fae548d3Szrj       expression_and_evaluate (&operand);
348*fae548d3Szrj       if (operand.X_op != O_constant)
349*fae548d3Szrj 	as_bad (_("non-constant expression in \".elseif\" statement"));
350*fae548d3Szrj 
351*fae548d3Szrj       switch ((operatorT) arg)
352*fae548d3Szrj 	{
353*fae548d3Szrj 	case O_eq: t = operand.X_add_number == 0; break;
354*fae548d3Szrj 	case O_ne: t = operand.X_add_number != 0; break;
355*fae548d3Szrj 	case O_lt: t = operand.X_add_number < 0; break;
356*fae548d3Szrj 	case O_le: t = operand.X_add_number <= 0; break;
357*fae548d3Szrj 	case O_ge: t = operand.X_add_number >= 0; break;
358*fae548d3Szrj 	case O_gt: t = operand.X_add_number > 0; break;
359*fae548d3Szrj 	default:
360*fae548d3Szrj 	  abort ();
361*fae548d3Szrj 	  return;
362*fae548d3Szrj 	}
363*fae548d3Szrj 
364*fae548d3Szrj       current_cframe->ignoring = current_cframe->dead_tree || ! t;
365*fae548d3Szrj     }
366*fae548d3Szrj 
367*fae548d3Szrj   if (LISTING_SKIP_COND ()
368*fae548d3Szrj       && (current_cframe->previous_cframe == NULL
369*fae548d3Szrj 	  || ! current_cframe->previous_cframe->ignoring))
370*fae548d3Szrj     {
371*fae548d3Szrj       if (! current_cframe->ignoring)
372*fae548d3Szrj 	listing_list (1);
373*fae548d3Szrj       else
374*fae548d3Szrj 	listing_list (2);
375*fae548d3Szrj     }
376*fae548d3Szrj 
377*fae548d3Szrj   demand_empty_rest_of_line ();
378*fae548d3Szrj }
379*fae548d3Szrj 
380*fae548d3Szrj void
s_endif(int arg ATTRIBUTE_UNUSED)381*fae548d3Szrj s_endif (int arg ATTRIBUTE_UNUSED)
382*fae548d3Szrj {
383*fae548d3Szrj   struct conditional_frame *hold;
384*fae548d3Szrj 
385*fae548d3Szrj   if (current_cframe == NULL)
386*fae548d3Szrj     {
387*fae548d3Szrj       as_bad (_("\".endif\" without \".if\""));
388*fae548d3Szrj     }
389*fae548d3Szrj   else
390*fae548d3Szrj     {
391*fae548d3Szrj       if (LISTING_SKIP_COND ()
392*fae548d3Szrj 	  && current_cframe->ignoring
393*fae548d3Szrj 	  && (current_cframe->previous_cframe == NULL
394*fae548d3Szrj 	      || ! current_cframe->previous_cframe->ignoring))
395*fae548d3Szrj 	listing_list (1);
396*fae548d3Szrj 
397*fae548d3Szrj       hold = current_cframe;
398*fae548d3Szrj       current_cframe = current_cframe->previous_cframe;
399*fae548d3Szrj       obstack_free (&cond_obstack, hold);
400*fae548d3Szrj     }				/* if one pop too many */
401*fae548d3Szrj 
402*fae548d3Szrj   if (flag_mri)
403*fae548d3Szrj     {
404*fae548d3Szrj       while (! is_end_of_line[(unsigned char) *input_line_pointer])
405*fae548d3Szrj 	++input_line_pointer;
406*fae548d3Szrj     }
407*fae548d3Szrj 
408*fae548d3Szrj   demand_empty_rest_of_line ();
409*fae548d3Szrj }
410*fae548d3Szrj 
411*fae548d3Szrj void
s_else(int arg ATTRIBUTE_UNUSED)412*fae548d3Szrj s_else (int arg ATTRIBUTE_UNUSED)
413*fae548d3Szrj {
414*fae548d3Szrj   if (current_cframe == NULL)
415*fae548d3Szrj     {
416*fae548d3Szrj       as_bad (_("\".else\" without matching \".if\""));
417*fae548d3Szrj     }
418*fae548d3Szrj   else if (current_cframe->else_seen)
419*fae548d3Szrj     {
420*fae548d3Szrj       as_bad (_("duplicate \".else\""));
421*fae548d3Szrj       as_bad_where (current_cframe->else_file_line.file,
422*fae548d3Szrj 		    current_cframe->else_file_line.line,
423*fae548d3Szrj 		    _("here is the previous \".else\""));
424*fae548d3Szrj       as_bad_where (current_cframe->if_file_line.file,
425*fae548d3Szrj 		    current_cframe->if_file_line.line,
426*fae548d3Szrj 		    _("here is the previous \".if\""));
427*fae548d3Szrj     }
428*fae548d3Szrj   else
429*fae548d3Szrj     {
430*fae548d3Szrj       current_cframe->else_file_line.file
431*fae548d3Szrj        	= as_where (&current_cframe->else_file_line.line);
432*fae548d3Szrj 
433*fae548d3Szrj       current_cframe->ignoring =
434*fae548d3Szrj 	current_cframe->dead_tree | !current_cframe->ignoring;
435*fae548d3Szrj 
436*fae548d3Szrj       if (LISTING_SKIP_COND ()
437*fae548d3Szrj 	  && (current_cframe->previous_cframe == NULL
438*fae548d3Szrj 	      || ! current_cframe->previous_cframe->ignoring))
439*fae548d3Szrj 	{
440*fae548d3Szrj 	  if (! current_cframe->ignoring)
441*fae548d3Szrj 	    listing_list (1);
442*fae548d3Szrj 	  else
443*fae548d3Szrj 	    listing_list (2);
444*fae548d3Szrj 	}
445*fae548d3Szrj 
446*fae548d3Szrj       current_cframe->else_seen = 1;
447*fae548d3Szrj     }
448*fae548d3Szrj 
449*fae548d3Szrj   if (flag_mri)
450*fae548d3Szrj     {
451*fae548d3Szrj       while (! is_end_of_line[(unsigned char) *input_line_pointer])
452*fae548d3Szrj 	++input_line_pointer;
453*fae548d3Szrj     }
454*fae548d3Szrj 
455*fae548d3Szrj   demand_empty_rest_of_line ();
456*fae548d3Szrj }
457*fae548d3Szrj 
458*fae548d3Szrj void
s_ifeqs(int arg)459*fae548d3Szrj s_ifeqs (int arg)
460*fae548d3Szrj {
461*fae548d3Szrj   char *s1, *s2;
462*fae548d3Szrj   int len1, len2;
463*fae548d3Szrj   int res;
464*fae548d3Szrj   struct conditional_frame cframe;
465*fae548d3Szrj 
466*fae548d3Szrj   s1 = demand_copy_C_string (&len1);
467*fae548d3Szrj 
468*fae548d3Szrj   SKIP_WHITESPACE ();
469*fae548d3Szrj   if (*input_line_pointer != ',')
470*fae548d3Szrj     {
471*fae548d3Szrj       as_bad (_(".ifeqs syntax error"));
472*fae548d3Szrj       ignore_rest_of_line ();
473*fae548d3Szrj       return;
474*fae548d3Szrj     }
475*fae548d3Szrj 
476*fae548d3Szrj   ++input_line_pointer;
477*fae548d3Szrj 
478*fae548d3Szrj   s2 = demand_copy_C_string (&len2);
479*fae548d3Szrj 
480*fae548d3Szrj   res = len1 == len2 && strncmp (s1, s2, len1) == 0;
481*fae548d3Szrj 
482*fae548d3Szrj   initialize_cframe (&cframe);
483*fae548d3Szrj   cframe.ignoring = cframe.dead_tree || ! (res ^ arg);
484*fae548d3Szrj   current_cframe =
485*fae548d3Szrj     (struct conditional_frame *) obstack_alloc (&cond_obstack, sizeof cframe);
486*fae548d3Szrj   memcpy (current_cframe, &cframe, sizeof cframe);
487*fae548d3Szrj 
488*fae548d3Szrj   if (LISTING_SKIP_COND ()
489*fae548d3Szrj       && cframe.ignoring
490*fae548d3Szrj       && (cframe.previous_cframe == NULL
491*fae548d3Szrj 	  || ! cframe.previous_cframe->ignoring))
492*fae548d3Szrj     listing_list (2);
493*fae548d3Szrj 
494*fae548d3Szrj   demand_empty_rest_of_line ();
495*fae548d3Szrj }
496*fae548d3Szrj 
497*fae548d3Szrj int
ignore_input(void)498*fae548d3Szrj ignore_input (void)
499*fae548d3Szrj {
500*fae548d3Szrj   char *s;
501*fae548d3Szrj 
502*fae548d3Szrj   s = input_line_pointer;
503*fae548d3Szrj 
504*fae548d3Szrj   if (NO_PSEUDO_DOT || flag_m68k_mri)
505*fae548d3Szrj     {
506*fae548d3Szrj       if (s[-1] != '.')
507*fae548d3Szrj 	--s;
508*fae548d3Szrj     }
509*fae548d3Szrj   else
510*fae548d3Szrj     {
511*fae548d3Szrj       if (s[-1] != '.')
512*fae548d3Szrj 	return (current_cframe != NULL) && (current_cframe->ignoring);
513*fae548d3Szrj     }
514*fae548d3Szrj 
515*fae548d3Szrj   /* We cannot ignore certain pseudo ops.  */
516*fae548d3Szrj   if (((s[0] == 'i'
517*fae548d3Szrj 	|| s[0] == 'I')
518*fae548d3Szrj        && (!strncasecmp (s, "if", 2)
519*fae548d3Szrj 	   || !strncasecmp (s, "ifdef", 5)
520*fae548d3Szrj 	   || !strncasecmp (s, "ifndef", 6)))
521*fae548d3Szrj       || ((s[0] == 'e'
522*fae548d3Szrj 	   || s[0] == 'E')
523*fae548d3Szrj 	  && (!strncasecmp (s, "else", 4)
524*fae548d3Szrj 	      || !strncasecmp (s, "endif", 5)
525*fae548d3Szrj 	      || !strncasecmp (s, "endc", 4))))
526*fae548d3Szrj     return 0;
527*fae548d3Szrj 
528*fae548d3Szrj   return (current_cframe != NULL) && (current_cframe->ignoring);
529*fae548d3Szrj }
530*fae548d3Szrj 
531*fae548d3Szrj static void
initialize_cframe(struct conditional_frame * cframe)532*fae548d3Szrj initialize_cframe (struct conditional_frame *cframe)
533*fae548d3Szrj {
534*fae548d3Szrj   memset (cframe, 0, sizeof (*cframe));
535*fae548d3Szrj   cframe->if_file_line.file
536*fae548d3Szrj 	    = as_where (&cframe->if_file_line.line);
537*fae548d3Szrj   cframe->previous_cframe = current_cframe;
538*fae548d3Szrj   cframe->dead_tree = current_cframe != NULL && current_cframe->ignoring;
539*fae548d3Szrj   cframe->macro_nest = macro_nest;
540*fae548d3Szrj }
541*fae548d3Szrj 
542*fae548d3Szrj /* Give an error if a conditional is unterminated inside a macro or
543*fae548d3Szrj    the assembly as a whole.  If NEST is non negative, we are being
544*fae548d3Szrj    called because of the end of a macro expansion.  If NEST is
545*fae548d3Szrj    negative, we are being called at the of the input files.  */
546*fae548d3Szrj 
547*fae548d3Szrj void
cond_finish_check(int nest)548*fae548d3Szrj cond_finish_check (int nest)
549*fae548d3Szrj {
550*fae548d3Szrj   if (current_cframe != NULL && current_cframe->macro_nest >= nest)
551*fae548d3Szrj     {
552*fae548d3Szrj       if (nest >= 0)
553*fae548d3Szrj 	as_bad (_("end of macro inside conditional"));
554*fae548d3Szrj       else
555*fae548d3Szrj 	as_bad (_("end of file inside conditional"));
556*fae548d3Szrj 
557*fae548d3Szrj       as_bad_where (current_cframe->if_file_line.file,
558*fae548d3Szrj 		    current_cframe->if_file_line.line,
559*fae548d3Szrj 		    _("here is the start of the unterminated conditional"));
560*fae548d3Szrj       if (current_cframe->else_seen)
561*fae548d3Szrj 	as_bad_where (current_cframe->else_file_line.file,
562*fae548d3Szrj 		      current_cframe->else_file_line.line,
563*fae548d3Szrj 		      _("here is the \"else\" of the unterminated conditional"));
564*fae548d3Szrj     }
565*fae548d3Szrj }
566*fae548d3Szrj 
567*fae548d3Szrj /* This function is called when we exit out of a macro.  We assume
568*fae548d3Szrj    that any conditionals which began within the macro are correctly
569*fae548d3Szrj    nested, and just pop them off the stack.  */
570*fae548d3Szrj 
571*fae548d3Szrj void
cond_exit_macro(int nest)572*fae548d3Szrj cond_exit_macro (int nest)
573*fae548d3Szrj {
574*fae548d3Szrj   while (current_cframe != NULL && current_cframe->macro_nest >= nest)
575*fae548d3Szrj     {
576*fae548d3Szrj       struct conditional_frame *hold;
577*fae548d3Szrj 
578*fae548d3Szrj       hold = current_cframe;
579*fae548d3Szrj       current_cframe = current_cframe->previous_cframe;
580*fae548d3Szrj       obstack_free (&cond_obstack, hold);
581*fae548d3Szrj     }
582*fae548d3Szrj }
583