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 (¤t_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 (¤t_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