Subversion Repositories Kolibri OS

Rev

Rev 5222 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

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