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