]>
Commit | Line | Data |
---|---|---|
fecd2382 RP |
1 | /* cond.c - conditional assembly pseudo-ops, and .include |
2 | Copyright (C) 1990, 1991 Free Software Foundation, Inc. | |
a39116f1 RP |
3 | |
4 | This file is part of GAS, the GNU Assembler. | |
5 | ||
6 | GAS is free software; you can redistribute it and/or modify | |
7 | it under the terms of the GNU General Public License as published by | |
8 | the Free Software Foundation; either version 2, or (at your option) | |
9 | any later version. | |
10 | ||
11 | GAS is distributed in the hope that it will be useful, | |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | GNU General Public License for more details. | |
15 | ||
16 | You should have received a copy of the GNU General Public License | |
17 | along with GAS; see the file COPYING. If not, write to | |
18 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ | |
fecd2382 | 19 | |
a39116f1 | 20 | #include "as.h" |
fecd2382 | 21 | |
a39116f1 | 22 | #include "obstack.h" |
fecd2382 | 23 | |
a39116f1 RP |
24 | /* This is allocated to grow and shrink as .ifdef/.endif pairs are scanned. */ |
25 | struct obstack cond_obstack; | |
fecd2382 | 26 | |
a39116f1 RP |
27 | struct file_line { |
28 | char *logical_file; | |
29 | int logical_line; | |
30 | char *physical_file; | |
31 | int physical_line; | |
32 | }; /* file_line */ | |
fecd2382 | 33 | |
a39116f1 RP |
34 | /* This is what we push and pop. */ |
35 | struct conditional_frame { | |
36 | struct file_line if_file_line; /* the source file & line number of the "if" */ | |
37 | struct file_line else_file_line; /* the source file & line of the "else" */ | |
38 | struct conditional_frame *previous_cframe; | |
39 | int else_seen; /* have we seen an else yet? */ | |
40 | int ignoring; /* if we are currently ignoring input. */ | |
41 | int dead_tree; /* if a conditional at a higher level is ignoring input. */ | |
42 | }; /* conditional_frame */ | |
fecd2382 | 43 | |
a39116f1 | 44 | #ifdef __STDC__ |
fecd2382 | 45 | |
a39116f1 RP |
46 | static void get_file_line(struct file_line *into); |
47 | static void initialize_cframe(struct conditional_frame *cframe); | |
48 | static void set_file_line(struct file_line *from); | |
49 | ||
50 | #else | |
51 | ||
52 | static void get_file_line(); | |
53 | static void initialize_cframe(); | |
54 | static void set_file_line(); | |
55 | ||
56 | #endif | |
57 | ||
58 | static struct conditional_frame *current_cframe = NULL; | |
fecd2382 RP |
59 | |
60 | void s_ifdef(arg) | |
61 | int arg; | |
62 | { | |
a39116f1 RP |
63 | register char *name; /* points to name of symbol */ |
64 | register struct symbol *symbolP; /* Points to symbol */ | |
65 | struct conditional_frame cframe; | |
fecd2382 RP |
66 | |
67 | SKIP_WHITESPACE(); /* Leading whitespace is part of operand. */ | |
68 | name = input_line_pointer; | |
a39116f1 | 69 | |
fecd2382 | 70 | if (!is_name_beginner(*name)) { |
a39116f1 RP |
71 | as_bad("invalid identifier for \".ifdef\""); |
72 | obstack_1grow(&cond_obstack, 0); | |
fecd2382 RP |
73 | } else { |
74 | get_symbol_end(); | |
75 | ++input_line_pointer; | |
76 | symbolP = symbol_find(name); | |
77 | ||
a39116f1 RP |
78 | initialize_cframe(&cframe); |
79 | cframe.ignoring = cframe.dead_tree && !((symbolP != 0) ^ arg); | |
80 | current_cframe = (struct conditional_frame *) obstack_copy(&cond_obstack, &cframe, sizeof(cframe)); | |
81 | } /* if a valid identifyer name */ | |
82 | ||
83 | return; | |
fecd2382 RP |
84 | } /* s_ifdef() */ |
85 | ||
fecd2382 RP |
86 | void s_if(arg) |
87 | int arg; | |
88 | { | |
89 | expressionS operand; | |
a39116f1 | 90 | struct conditional_frame cframe; |
fecd2382 | 91 | |
a39116f1 | 92 | SKIP_WHITESPACE(); /* Leading whitespace is part of operand. */ |
fecd2382 RP |
93 | expr(0, &operand); |
94 | ||
95 | if (operand.X_add_symbol != NULL | |
a39116f1 RP |
96 | || operand.X_subtract_symbol != NULL) { |
97 | as_bad("non-constant expression in \".if\" statement"); | |
98 | } /* bad condition */ | |
fecd2382 RP |
99 | |
100 | /* If the above error is signaled, this will dispatch | |
101 | using an undefined result. No big deal. */ | |
a39116f1 RP |
102 | initialize_cframe(&cframe); |
103 | cframe.ignoring = cframe.dead_tree || !((operand.X_add_number != 0) ^ arg); | |
104 | current_cframe = (struct conditional_frame *) obstack_copy(&cond_obstack, &cframe, sizeof(cframe)); | |
105 | return; | |
fecd2382 RP |
106 | } /* s_if() */ |
107 | ||
108 | void s_endif(arg) | |
109 | int arg; | |
110 | { | |
a39116f1 | 111 | struct conditional_frame *hold; |
fecd2382 | 112 | |
a39116f1 RP |
113 | if (current_cframe == NULL) { |
114 | as_bad("\".endif\" without \".if\""); | |
fecd2382 | 115 | } else { |
a39116f1 RP |
116 | hold = current_cframe; |
117 | current_cframe = current_cframe->previous_cframe; | |
118 | obstack_free(&cond_obstack, hold); | |
119 | } /* if one pop too many */ | |
120 | ||
121 | return; | |
fecd2382 RP |
122 | } /* s_endif() */ |
123 | ||
124 | void s_else(arg) | |
125 | int arg; | |
126 | { | |
a39116f1 RP |
127 | if (current_cframe == NULL) { |
128 | as_bad(".else without matching .if - ignored"); | |
129 | ||
130 | } else if (current_cframe->else_seen) { | |
131 | struct file_line hold; | |
132 | as_bad("duplicate \"else\" - ignored"); | |
133 | ||
134 | get_file_line(&hold); | |
135 | set_file_line(¤t_cframe->else_file_line); | |
136 | as_bad("here is the previous \"else\"."); | |
137 | set_file_line(¤t_cframe->if_file_line); | |
138 | as_bad("here is the matching \".if\"."); | |
139 | set_file_line(&hold); | |
140 | ||
fecd2382 | 141 | } else { |
a39116f1 RP |
142 | get_file_line(¤t_cframe->else_file_line); |
143 | ||
144 | if (!current_cframe->dead_tree) { | |
145 | current_cframe->ignoring = !current_cframe->ignoring; | |
146 | } /* if not a dead tree */ | |
147 | ||
148 | current_cframe->else_seen = 1; | |
149 | } /* if error else do it */ | |
150 | ||
151 | return; | |
fecd2382 RP |
152 | } /* s_else() */ |
153 | ||
154 | void s_ifeqs(arg) | |
155 | int arg; | |
156 | { | |
157 | as_bad("ifeqs not implemented."); | |
a39116f1 RP |
158 | |
159 | return; | |
fecd2382 RP |
160 | } /* s_ifeqs() */ |
161 | ||
162 | void s_end(arg) | |
163 | int arg; | |
164 | { | |
a39116f1 | 165 | return; |
fecd2382 RP |
166 | } /* s_end() */ |
167 | ||
168 | int ignore_input() { | |
a39116f1 RP |
169 | char *ptr = obstack_next_free (&cond_obstack); |
170 | ||
171 | /* We cannot ignore certain pseudo ops. */ | |
172 | if (input_line_pointer[-1] == '.' | |
173 | && ((input_line_pointer[0] == 'i' | |
174 | && (!strncmp (input_line_pointer, "if", 2) | |
175 | || !strncmp (input_line_pointer, "ifdef", 5) | |
176 | || !strncmp (input_line_pointer, "ifndef", 6))) | |
177 | || (input_line_pointer[0] == 'e' | |
178 | && (!strncmp (input_line_pointer, "else", 4) | |
179 | || !strncmp (input_line_pointer, "endif", 5))))) { | |
180 | return 0; | |
181 | } | |
182 | ||
183 | return((current_cframe != NULL) && (current_cframe->ignoring)); | |
fecd2382 RP |
184 | } /* ignore_input() */ |
185 | ||
a39116f1 RP |
186 | static void initialize_cframe(cframe) |
187 | struct conditional_frame *cframe; | |
188 | { | |
189 | memset(cframe, 0, sizeof(*cframe)); | |
190 | get_file_line(&(cframe->if_file_line)); | |
191 | cframe->previous_cframe = current_cframe; | |
192 | cframe->dead_tree = current_cframe != NULL && current_cframe->ignoring; | |
193 | ||
194 | return; | |
195 | } /* initialize_cframe() */ | |
196 | ||
197 | static void get_file_line(into) | |
198 | struct file_line *into; | |
199 | { | |
200 | extern char *logical_input_file; | |
201 | extern char *physical_input_file; | |
202 | extern int logical_input_line; | |
203 | extern int physical_input_line; | |
204 | ||
205 | into->logical_file = logical_input_file; | |
206 | into->logical_line = logical_input_line; | |
207 | into->physical_file = physical_input_file; | |
208 | into->physical_line = physical_input_line; | |
209 | ||
210 | return; | |
211 | } /* get_file_line() */ | |
212 | ||
213 | static void set_file_line(from) | |
214 | struct file_line *from; | |
215 | { | |
216 | extern char *logical_input_file; | |
217 | extern char *physical_input_file; | |
218 | extern int logical_input_line; | |
219 | extern int physical_input_line; | |
220 | ||
221 | logical_input_file = from->logical_file; | |
222 | logical_input_line = from->logical_line; | |
223 | physical_input_file = from->physical_file; | |
224 | physical_input_line = from->physical_line; | |
225 | return; | |
226 | } /* set_file_line() */ | |
227 | ||
228 | /* | |
229 | * Local Variables: | |
230 | * fill-column: 131 | |
231 | * comment-column: 0 | |
232 | * End: | |
233 | */ | |
234 | ||
fecd2382 | 235 | /* end of cond.c */ |