1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22: #include "as.h"
23: #include "sb.h"
24: #include "macro.h"
25:
26: #include "obstack.h"
27:
28:
29:
30: struct obstack cond_obstack;
31:
32: struct file_line {
33: char *file;
34: unsigned int line;
35: };
36:
37:
38:
39:
40: struct conditional_frame {
41:
42: struct file_line if_file_line;
43:
44: struct file_line else_file_line;
45:
46: struct conditional_frame *previous_cframe;
47:
48: int else_seen;
49:
50: int ignoring;
51:
52:
53:
54: int dead_tree;
55:
56: int macro_nest;
57: };
58:
59: static void initialize_cframe (struct conditional_frame *cframe);
60: static char *get_mri_string (int, int *);
61:
62: static struct conditional_frame *current_cframe = NULL;
63:
64:
65:
66:
67: void
68: s_ifdef (int test_defined)
69: {
70:
71: char *name;
72:
73: symbolS *symbolP;
74: struct conditional_frame cframe;
75: char c;
76:
77:
78: SKIP_WHITESPACE ();
79: name = input_line_pointer;
80:
81: if (!is_name_beginner (*name))
82: {
83: as_bad (_("invalid identifier for \".ifdef\""));
84: obstack_1grow (&cond_obstack, 0);
85: ignore_rest_of_line ();
86: return;
87: }
88:
89: c = get_symbol_end ();
90: symbolP = symbol_find (name);
91: *input_line_pointer = c;
92:
93: initialize_cframe (&cframe);
94:
95: if (cframe.dead_tree)
96: cframe.ignoring = 1;
97: else
98: {
99: int is_defined;
100:
101:
102:
103:
104: is_defined =
105: symbolP != NULL
106: && (S_IS_DEFINED (symbolP) || symbol_equated_p (symbolP))
107: && S_GET_SEGMENT (symbolP) != reg_section;
108:
109: cframe.ignoring = ! (test_defined ^ is_defined);
110: }
111:
112: current_cframe = ((struct conditional_frame *)
113: obstack_copy (&cond_obstack, &cframe,
114: sizeof (cframe)));
115:
116: if (LISTING_SKIP_COND ()
117: && cframe.ignoring
118: && (cframe.previous_cframe == NULL
119: || ! cframe.previous_cframe->ignoring))
120: listing_list (2);
121:
122: demand_empty_rest_of_line ();
123: }
124:
125: void
126: s_if (int arg)
127: {
128: expressionS operand;
129: struct conditional_frame cframe;
130: int t;
131: char *stop = NULL;
132: char stopc;
133:
134: if (flag_mri)
135: stop = mri_comment_field (&stopc);
136:
137:
138: SKIP_WHITESPACE ();
139:
140: if (current_cframe != NULL && current_cframe->ignoring)
141: {
142: operand.X_add_number = 0;
143: while (! is_end_of_line[(unsigned char) *input_line_pointer])
144: ++input_line_pointer;
145: }
146: else
147: {
148: expression_and_evaluate (&operand);
149: if (operand.X_op != O_constant)
150: as_bad (_("non-constant expression in \".if\" statement"));
151: }
152:
153: switch ((operatorT) arg)
154: {
155: case O_eq: t = operand.X_add_number == 0; break;
156: case O_ne: t = operand.X_add_number != 0; break;
157: case O_lt: t = operand.X_add_number < 0; break;
158: case O_le: t = operand.X_add_number <= 0; break;
159: case O_ge: t = operand.X_add_number >= 0; break;
160: case O_gt: t = operand.X_add_number > 0; break;
161: default:
162: abort ();
163: return;
164: }
165:
166:
167:
168: initialize_cframe (&cframe);
169: cframe.ignoring = cframe.dead_tree || ! t;
170: current_cframe = ((struct conditional_frame *)
171: obstack_copy (&cond_obstack, &cframe, sizeof (cframe)));
172:
173: if (LISTING_SKIP_COND ()
174: && cframe.ignoring
175: && (cframe.previous_cframe == NULL
176: || ! cframe.previous_cframe->ignoring))
177: listing_list (2);
178:
179: if (flag_mri)
180: mri_comment_end (stop, stopc);
181:
182: demand_empty_rest_of_line ();
183: }
184:
185:
186:
187:
188: void
189: s_ifb (int test_blank)
190: {
191: struct conditional_frame cframe;
192:
193: initialize_cframe (&cframe);
194:
195: if (cframe.dead_tree)
196: cframe.ignoring = 1;
197: else
198: {
199: int is_eol;
200:
201: SKIP_WHITESPACE ();
202: is_eol = is_end_of_line[(unsigned char) *input_line_pointer];
203: cframe.ignoring = (test_blank == !is_eol);
204: }
205:
206: current_cframe = ((struct conditional_frame *)
207: obstack_copy (&cond_obstack, &cframe,
208: sizeof (cframe)));
209:
210: if (LISTING_SKIP_COND ()
211: && cframe.ignoring
212: && (cframe.previous_cframe == NULL
213: || ! cframe.previous_cframe->ignoring))
214: listing_list (2);
215:
216: ignore_rest_of_line ();
217: }
218:
219:
220:
221: static char *
222: get_mri_string (int terminator, int *len)
223: {
224: char *ret;
225: char *s;
226:
227: SKIP_WHITESPACE ();
228: s = ret = input_line_pointer;
229: if (*input_line_pointer == '\'')
230: {
231: ++s;
232: ++input_line_pointer;
233: while (! is_end_of_line[(unsigned char) *input_line_pointer])
234: {
235: *s++ = *input_line_pointer++;
236: if (s[-1] == '\'')
237: {
238: if (*input_line_pointer != '\'')
239: break;
240: ++input_line_pointer;
241: }
242: }
243: SKIP_WHITESPACE ();
244: }
245: else
246: {
247: while (*input_line_pointer != terminator
248: && ! is_end_of_line[(unsigned char) *input_line_pointer])
249: ++input_line_pointer;
250: s = input_line_pointer;
251: while (s > ret && (s[-1] == ' ' || s[-1] == '\t'))
252: --s;
253: }
254:
255: *len = s - ret;
256: return ret;
257: }
258:
259:
260:
261: void
262: s_ifc (int arg)
263: {
264: char *stop = NULL;
265: char stopc;
266: char *s1, *s2;
267: int len1, len2;
268: int res;
269: struct conditional_frame cframe;
270:
271: if (flag_mri)
272: stop = mri_comment_field (&stopc);
273:
274: s1 = get_mri_string (',', &len1);
275:
276: if (*input_line_pointer != ',')
277: as_bad (_("bad format for ifc or ifnc"));
278: else
279: ++input_line_pointer;
280:
281: s2 = get_mri_string (';', &len2);
282:
283: res = len1 == len2 && strncmp (s1, s2, len1) == 0;
284:
285: initialize_cframe (&cframe);
286: cframe.ignoring = cframe.dead_tree || ! (res ^ arg);
287: current_cframe = ((struct conditional_frame *)
288: obstack_copy (&cond_obstack, &cframe, sizeof (cframe)));
289:
290: if (LISTING_SKIP_COND ()
291: && cframe.ignoring
292: && (cframe.previous_cframe == NULL
293: || ! cframe.previous_cframe->ignoring))
294: listing_list (2);
295:
296: if (flag_mri)
297: mri_comment_end (stop, stopc);
298:
299: demand_empty_rest_of_line ();
300: }
301:
302: void
303: s_elseif (int arg)
304: {
305: if (current_cframe == NULL)
306: {
307: as_bad (_("\".elseif\" without matching \".if\""));
308: }
309: else if (current_cframe->else_seen)
310: {
311: as_bad (_("\".elseif\" after \".else\""));
312: as_bad_where (current_cframe->else_file_line.file,
313: current_cframe->else_file_line.line,
314: _("here is the previous \"else\""));
315: as_bad_where (current_cframe->if_file_line.file,
316: current_cframe->if_file_line.line,
317: _("here is the previous \"if\""));
318: }
319: else
320: {
321: as_where (¤t_cframe->else_file_line.file,
322: ¤t_cframe->else_file_line.line);
323:
324: current_cframe->dead_tree |= !current_cframe->ignoring;
325: current_cframe->ignoring = current_cframe->dead_tree;
326: }
327:
328: if (current_cframe == NULL || current_cframe->ignoring)
329: {
330: while (! is_end_of_line[(unsigned char) *input_line_pointer])
331: ++input_line_pointer;
332:
333: if (current_cframe == NULL)
334: return;
335: }
336: else
337: {
338: expressionS operand;
339: int t;
340:
341:
342: SKIP_WHITESPACE ();
343:
344: expression_and_evaluate (&operand);
345: if (operand.X_op != O_constant)
346: as_bad (_("non-constant expression in \".elseif\" statement"));
347:
348: switch ((operatorT) arg)
349: {
350: case O_eq: t = operand.X_add_number == 0; break;
351: case O_ne: t = operand.X_add_number != 0; break;
352: case O_lt: t = operand.X_add_number < 0; break;
353: case O_le: t = operand.X_add_number <= 0; break;
354: case O_ge: t = operand.X_add_number >= 0; break;
355: case O_gt: t = operand.X_add_number > 0; break;
356: default:
357: abort ();
358: return;
359: }
360:
361: current_cframe->ignoring = current_cframe->dead_tree || ! t;
362: }
363:
364: if (LISTING_SKIP_COND ()
365: && (current_cframe->previous_cframe == NULL
366: || ! current_cframe->previous_cframe->ignoring))
367: {
368: if (! current_cframe->ignoring)
369: listing_list (1);
370: else
371: listing_list (2);
372: }
373:
374: demand_empty_rest_of_line ();
375: }
376:
377: void
378: s_endif (int arg ATTRIBUTE_UNUSED)
379: {
380: struct conditional_frame *hold;
381:
382: if (current_cframe == NULL)
383: {
384: as_bad (_("\".endif\" without \".if\""));
385: }
386: else
387: {
388: if (LISTING_SKIP_COND ()
389: && current_cframe->ignoring
390: && (current_cframe->previous_cframe == NULL
391: || ! current_cframe->previous_cframe->ignoring))
392: listing_list (1);
393:
394: hold = current_cframe;
395: current_cframe = current_cframe->previous_cframe;
396: obstack_free (&cond_obstack, hold);
397: }
398:
399: if (flag_mri)
400: {
401: while (! is_end_of_line[(unsigned char) *input_line_pointer])
402: ++input_line_pointer;
403: }
404:
405: demand_empty_rest_of_line ();
406: }
407:
408: void
409: s_else (int arg ATTRIBUTE_UNUSED)
410: {
411: if (current_cframe == NULL)
412: {
413: as_bad (_("\".else\" without matching \".if\""));
414: }
415: else if (current_cframe->else_seen)
416: {
417: as_bad (_("duplicate \"else\""));
418: as_bad_where (current_cframe->else_file_line.file,
419: current_cframe->else_file_line.line,
420: _("here is the previous \"else\""));
421: as_bad_where (current_cframe->if_file_line.file,
422: current_cframe->if_file_line.line,
423: _("here is the previous \"if\""));
424: }
425: else
426: {
427: as_where (¤t_cframe->else_file_line.file,
428: ¤t_cframe->else_file_line.line);
429:
430: current_cframe->ignoring =
431: current_cframe->dead_tree | !current_cframe->ignoring;
432:
433: if (LISTING_SKIP_COND ()
434: && (current_cframe->previous_cframe == NULL
435: || ! current_cframe->previous_cframe->ignoring))
436: {
437: if (! current_cframe->ignoring)
438: listing_list (1);
439: else
440: listing_list (2);
441: }
442:
443: current_cframe->else_seen = 1;
444: }
445:
446: if (flag_mri)
447: {
448: while (! is_end_of_line[(unsigned char) *input_line_pointer])
449: ++input_line_pointer;
450: }
451:
452: demand_empty_rest_of_line ();
453: }
454:
455: void
456: s_ifeqs (int arg)
457: {
458: char *s1, *s2;
459: int len1, len2;
460: int res;
461: struct conditional_frame cframe;
462:
463: s1 = demand_copy_C_string (&len1);
464:
465: SKIP_WHITESPACE ();
466: if (*input_line_pointer != ',')
467: {
468: as_bad (_(".ifeqs syntax error"));
469: ignore_rest_of_line ();
470: return;
471: }
472:
473: ++input_line_pointer;
474:
475: s2 = demand_copy_C_string (&len2);
476:
477: res = len1 == len2 && strncmp (s1, s2, len1) == 0;
478:
479: initialize_cframe (&cframe);
480: cframe.ignoring = cframe.dead_tree || ! (res ^ arg);
481: current_cframe = ((struct conditional_frame *)
482: obstack_copy (&cond_obstack, &cframe, sizeof (cframe)));
483:
484: if (LISTING_SKIP_COND ()
485: && cframe.ignoring
486: && (cframe.previous_cframe == NULL
487: || ! cframe.previous_cframe->ignoring))
488: listing_list (2);
489:
490: demand_empty_rest_of_line ();
491: }
492:
493: int
494: ignore_input (void)
495: {
496: char *s;
497:
498: s = input_line_pointer;
499:
500: if (NO_PSEUDO_DOT || flag_m68k_mri)
501: {
502: if (s[-1] != '.')
503: --s;
504: }
505: else
506: {
507: if (s[-1] != '.')
508: return (current_cframe != NULL) && (current_cframe->ignoring);
509: }
510:
511:
512: if (((s[0] == 'i'
513: || s[0] == 'I')
514: && (!strncasecmp (s, "if", 2)
515: || !strncasecmp (s, "ifdef", 5)
516: || !strncasecmp (s, "ifndef", 6)))
517: || ((s[0] == 'e'
518: || s[0] == 'E')
519: && (!strncasecmp (s, "else", 4)
520: || !strncasecmp (s, "endif", 5)
521: || !strncasecmp (s, "endc", 4))))
522: return 0;
523:
524: return (current_cframe != NULL) && (current_cframe->ignoring);
525: }
526:
527: static void
528: initialize_cframe (struct conditional_frame *cframe)
529: {
530: memset (cframe, 0, sizeof (*cframe));
531: as_where (&cframe->if_file_line.file,
532: &cframe->if_file_line.line);
533: cframe->previous_cframe = current_cframe;
534: cframe->dead_tree = current_cframe != NULL && current_cframe->ignoring;
535: cframe->macro_nest = macro_nest;
536: }
537:
538:
539:
540:
541:
542:
543: void
544: cond_finish_check (int nest)
545: {
546: if (current_cframe != NULL && current_cframe->macro_nest >= nest)
547: {
548: if (nest >= 0)
549: as_bad (_("end of macro inside conditional"));
550: else
551: as_bad (_("end of file inside conditional"));
552: as_bad_where (current_cframe->if_file_line.file,
553: current_cframe->if_file_line.line,
554: _("here is the start of the unterminated conditional"));
555: if (current_cframe->else_seen)
556: as_bad_where (current_cframe->else_file_line.file,
557: current_cframe->else_file_line.line,
558: _("here is the \"else\" of the unterminated conditional"));
559: }
560: }
561:
562:
563:
564:
565:
566: void
567: cond_exit_macro (int nest)
568: {
569: while (current_cframe != NULL && current_cframe->macro_nest >= nest)
570: {
571: struct conditional_frame *hold;
572:
573: hold = current_cframe;
574: current_cframe = current_cframe->previous_cframe;
575: obstack_free (&cond_obstack, hold);
576: }
577: }