configure.host: fix shell syntax errors
[deliverable/binutils-gdb.git] / gas / subsegs.c
CommitLineData
fecd2382 1/* subsegs.c - subsegments -
cc886e3d
SS
2 Copyright (C) 1987, 1990, 1991, 1992, 1993, 1994
3 Free Software Foundation, Inc.
604633ae 4
a39116f1 5 This file is part of GAS, the GNU Assembler.
604633ae 6
a39116f1
RP
7 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
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
604633ae 11
a39116f1
RP
12 GAS is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
604633ae 16
a39116f1
RP
17 You should have received a copy of the GNU General Public License
18 along with GAS; see the file COPYING. If not, write to
1356d77d 19 the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
fecd2382
RP
20
21/*
22 * Segments & sub-segments.
23 */
24
25#include "as.h"
26
27#include "subsegs.h"
28#include "obstack.h"
29
604633ae
ILT
30frchainS *frchain_root, *frchain_now;
31
32#ifndef BFD_ASSEMBLER
a39116f1
RP
33#ifdef MANY_SEGMENTS
34segment_info_type segment_info[SEG_MAXIMUM_ORDINAL];
35
a39116f1 36#else
604633ae
ILT
37/* Commented in "subsegs.h". */
38frchainS *data0_frchainP, *bss0_frchainP;
fecd2382 39
604633ae 40#endif /* MANY_SEGMENTS */
1356d77d 41char const *const seg_name[] =
604633ae
ILT
42{
43 "absolute",
a39116f1 44#ifdef MANY_SEGMENTS
604633ae 45 "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9",
a39116f1 46#else
604633ae
ILT
47 "text",
48 "data",
49 "bss",
50#endif /* MANY_SEGMENTS */
51 "unknown",
52 "ASSEMBLER-INTERNAL-LOGIC-ERROR!",
53 "expr",
54 "debug",
55 "transfert vector preload",
56 "transfert vector postload",
57 "register",
58 "",
59}; /* Used by error reporters, dumpers etc. */
dff770c8
ILT
60#else /* BFD_ASSEMBLER */
61
62/* Gas segment information for bfd_abs_section_ptr and
63 bfd_und_section_ptr. */
64static segment_info_type *abs_seg_info;
65static segment_info_type *und_seg_info;
66
604633ae 67#endif /* BFD_ASSEMBLER */
fecd2382 68
604633ae 69static void subseg_set_rest PARAMS ((segT, subsegT));
fecd2382
RP
70\f
71void
604633ae 72subsegs_begin ()
fecd2382 73{
604633ae
ILT
74 /* Check table(s) seg_name[], seg_N_TYPE[] is in correct order */
75#if !defined (MANY_SEGMENTS) && !defined (BFD_ASSEMBLER)
76 know (SEG_ABSOLUTE == 0);
77 know (SEG_TEXT == 1);
78 know (SEG_DATA == 2);
79 know (SEG_BSS == 3);
80 know (SEG_UNKNOWN == 4);
81 know (SEG_GOOF == 5);
82 know (SEG_EXPR == 6);
83 know (SEG_DEBUG == 7);
84 know (SEG_NTV == 8);
85 know (SEG_PTV == 9);
86 know (SEG_REGISTER == 10);
87 know (SEG_MAXIMUM_ORDINAL == SEG_REGISTER);
a39116f1 88#endif
604633ae 89
604633ae
ILT
90 frchain_root = NULL;
91 frchain_now = NULL; /* Warn new_subseg() that we are booting. */
92 /* Fake up 1st frag. It won't be used=> is ok if obstack...
93 pads the end of it for alignment. */
94 frag_now = (fragS *) obstack_alloc (&frags, SIZEOF_STRUCT_FRAG);
cc886e3d 95 memset (frag_now, 0, SIZEOF_STRUCT_FRAG);
604633ae
ILT
96
97#ifndef BFD_ASSEMBLER
98 /* This 1st frag will not be in any frchain.
99 We simply give subseg_new somewhere to scribble. */
100 now_subseg = 42; /* Lie for 1st call to subseg_new. */
a39116f1 101#ifdef MANY_SEGMENTS
604633ae
ILT
102 {
103 int i;
104 for (i = SEG_E0; i < SEG_UNKNOWN; i++)
105 {
106 subseg_set (i, 0);
107 segment_info[i].frchainP = frchain_now;
108 }
109 }
a39116f1 110#else
604633ae
ILT
111 subseg_set (SEG_DATA, 0); /* .data 0 */
112 data0_frchainP = frchain_now;
65bfcf2e 113
604633ae
ILT
114 subseg_set (SEG_BSS, 0);
115 bss0_frchainP = frchain_now;
116
117#endif /* ! MANY_SEGMENTS */
118#endif /* ! BFD_ASSEMBLER */
65bfcf2e 119
fecd2382
RP
120}
121\f
122/*
123 * subseg_change()
124 *
125 * Change the subsegment we are in, BUT DO NOT MAKE A NEW FRAG for the
126 * subsegment. If we are already in the correct subsegment, change nothing.
604633ae 127 * This is used eg as a worker for subseg_set [which does make a new frag_now]
fecd2382
RP
128 * and for changing segments after we have read the source. We construct eg
129 * fixSs even after the source file is read, so we do have to keep the
130 * segment context correct.
131 */
132void
604633ae
ILT
133subseg_change (seg, subseg)
134 register segT seg;
135 register int subseg;
fecd2382 136{
604633ae
ILT
137 now_seg = seg;
138 now_subseg = subseg;
139
140#ifdef BFD_ASSEMBLER
141 {
142 segment_info_type *seginfo;
143 seginfo = (segment_info_type *) bfd_get_section_userdata (stdoutput, seg);
144 if (! seginfo)
145 {
146 seginfo = (segment_info_type *) xmalloc (sizeof (*seginfo));
3c498933 147 memset ((PTR) seginfo, 0, sizeof (*seginfo));
dff770c8
ILT
148 seginfo->fix_root = NULL;
149 seginfo->fix_tail = NULL;
604633ae
ILT
150 seginfo->bfd_section = seg;
151 seginfo->sym = 0;
dff770c8
ILT
152 if (seg == bfd_abs_section_ptr)
153 abs_seg_info = seginfo;
154 else if (seg == bfd_und_section_ptr)
155 und_seg_info = seginfo;
156 else
157 bfd_set_section_userdata (stdoutput, seg, (PTR) seginfo);
604633ae
ILT
158 }
159 }
160#else
a39116f1 161#ifdef MANY_SEGMENTS
604633ae
ILT
162 seg_fix_rootP = &segment_info[seg].fix_root;
163 seg_fix_tailP = &segment_info[seg].fix_tail;
a39116f1 164#else
604633ae
ILT
165 if (seg == SEG_DATA)
166 {
167 seg_fix_rootP = &data_fix_root;
168 seg_fix_tailP = &data_fix_tail;
169 }
170 else if (seg == SEG_TEXT)
171 {
172 seg_fix_rootP = &text_fix_root;
173 seg_fix_tailP = &text_fix_tail;
174 }
175 else
176 {
177 know (seg == SEG_BSS);
178 seg_fix_rootP = &bss_fix_root;
179 seg_fix_tailP = &bss_fix_tail;
180 }
181
182#endif
a39116f1 183#endif
fecd2382
RP
184}
185\f
604633ae
ILT
186static void
187subseg_set_rest (seg, subseg)
188 segT seg;
189 subsegT subseg;
190{
191 long tmp; /* JF for obstack alignment hacking */
192 register frchainS *frcP; /* crawl frchain chain */
193 register frchainS **lastPP; /* address of last pointer */
194 frchainS *newP; /* address of new frchain */
195 register fragS *former_last_fragP;
196 register fragS *new_fragP;
197
198 if (frag_now) /* If not bootstrapping. */
199 {
1356d77d 200 frag_now->fr_fix = frag_now_fix ();
604633ae
ILT
201 frag_wane (frag_now); /* Close off any frag in old subseg. */
202 }
203 /*
204 * It would be nice to keep an obstack for each subsegment, if we swap
205 * subsegments a lot. Hence we would have much fewer frag_wanes().
206 */
207 {
208 obstack_finish (&frags);
209 /*
210 * If we don't do the above, the next object we put on obstack frags
211 * will appear to start at the fr_literal of the current frag.
212 * Also, above ensures that the next object will begin on a
213 * address that is aligned correctly for the engine that runs
214 * this program.
215 */
216 }
217 subseg_change (seg, (int) subseg);
218 /*
219 * Attempt to find or make a frchain for that sub seg.
220 * Crawl along chain of frchainSs, begins @ frchain_root.
221 * If we need to make a frchainS, link it into correct
222 * position of chain rooted in frchain_root.
223 */
224 for (frcP = *(lastPP = &frchain_root);
3b6d6f71 225 frcP && frcP->frch_seg <= seg;
604633ae
ILT
226 frcP = *(lastPP = &frcP->frch_next))
227 {
3b6d6f71 228 if (frcP->frch_seg == seg
604633ae
ILT
229 && frcP->frch_subseg >= subseg)
230 {
231 break;
232 }
233 }
234 /*
235 * frcP: Address of the 1st frchainS in correct segment with
236 * frch_subseg >= subseg.
237 * We want to either use this frchainS, or we want
238 * to insert a new frchainS just before it.
239 *
240 * If frcP==NULL, then we are at the end of the chain
241 * of frchainS-s. A NULL frcP means we fell off the end
242 * of the chain looking for a
243 * frch_subseg >= subseg, so we
244 * must make a new frchainS.
245 *
246 * If we ever maintain a pointer to
247 * the last frchainS in the chain, we change that pointer
248 * ONLY when frcP==NULL.
249 *
250 * lastPP: Address of the pointer with value frcP;
251 * Never NULL.
252 * May point to frchain_root.
253 *
254 */
255 if (!frcP
3b6d6f71 256 || (frcP->frch_seg > seg
604633ae
ILT
257 || frcP->frch_subseg > subseg)) /* Kinky logic only works with 2 segments. */
258 {
259 /*
260 * This should be the only code that creates a frchainS.
261 */
262 newP = (frchainS *) obstack_alloc (&frags, sizeof (frchainS));
1356d77d
ILT
263 newP->frch_root = 0;
264 newP->frch_subseg = subseg;
604633ae
ILT
265 newP->frch_seg = seg;
266 newP->frch_last = NULL;
cc886e3d
SS
267#ifdef BFD_ASSEMBLER
268 newP->fix_root = NULL;
269 newP->fix_tail = NULL;
270#endif
1356d77d
ILT
271 obstack_begin (&newP->frch_obstack, 5000);
272
273 *lastPP = newP;
274 newP->frch_next = frcP; /* perhaps NULL */
275 frcP = newP;
604633ae
ILT
276 }
277 /*
1356d77d 278 * Here with frcP pointing to the frchainS for subseg.
604633ae
ILT
279 */
280 frchain_now = frcP;
281 /*
282 * Make a fresh frag for the subsegment.
283 */
284 /* We expect this to happen on a correct boundary since it was
285 proceeded by a obstack_done(). */
286 tmp = obstack_alignment_mask (&frags); /* JF disable alignment */
287 obstack_alignment_mask (&frags) = 0;
288 frag_now = (fragS *) obstack_alloc (&frags, SIZEOF_STRUCT_FRAG);
289 memset (frag_now, 0, SIZEOF_STRUCT_FRAG);
290 obstack_alignment_mask (&frags) = tmp;
291 /* But we want any more chars to come immediately after the
292 structure we just made. */
293 new_fragP = frag_now;
294 new_fragP->fr_next = NULL;
295 /*
296 * Append new frag to current frchain.
297 */
298 former_last_fragP = frcP->frch_last;
299 if (former_last_fragP)
300 {
301 know (former_last_fragP->fr_next == NULL);
302 know (frchain_now->frch_root);
303 former_last_fragP->fr_next = new_fragP;
304 }
305 else
306 {
307 frcP->frch_root = new_fragP;
308 }
309 frcP->frch_last = new_fragP;
1356d77d
ILT
310
311 mri_common_symbol = NULL;
604633ae
ILT
312}
313
fecd2382 314/*
604633ae 315 * subseg_set(segT, subsegT)
fecd2382
RP
316 *
317 * If you attempt to change to the current subsegment, nothing happens.
318 *
319 * In: segT, subsegT code for new subsegment.
320 * frag_now -> incomplete frag for current subsegment.
321 * If frag_now==NULL, then there is no old, incomplete frag, so
322 * the old frag is not closed off.
323 *
324 * Out: now_subseg, now_seg updated.
325 * Frchain_now points to the (possibly new) struct frchain for this
326 * sub-segment.
327 * Frchain_root updated if needed.
328 */
329
604633ae
ILT
330#ifndef BFD_ASSEMBLER
331
332segT
333subseg_new (segname, subseg)
334 const char *segname;
335 subsegT subseg;
fecd2382 336{
604633ae
ILT
337 int i;
338
339 for (i = 0; i < (int) SEG_MAXIMUM_ORDINAL; i++)
340 {
341 const char *s;
342
343 s = segment_name ((segT) i);
344 if (strcmp (segname, s) == 0
345 || (segname[0] == '.'
346 && strcmp (segname + 1, s) == 0))
f8701a3f 347 {
604633ae
ILT
348 subseg_set ((segT) i, subseg);
349 return (segT) i;
350 }
351#ifdef obj_segment_name
352 s = obj_segment_name ((segT) i);
353 if (strcmp (segname, s) == 0
354 || (segname[0] == '.'
355 && strcmp (segname + 1, s) == 0))
356 {
357 subseg_set ((segT) i, subseg);
358 return (segT) i;
f8701a3f 359 }
a39116f1 360#endif
604633ae 361 }
fecd2382 362
604633ae
ILT
363#ifdef obj_add_segment
364 {
365 segT new_seg;
366 new_seg = obj_add_segment (segname);
367 subseg_set (new_seg, subseg);
368 return new_seg;
369 }
370#else
371 as_bad ("Attempt to switch to nonexistent segment \"%s\"", segname);
372 return now_seg;
373#endif
374}
375
376void
377subseg_set (seg, subseg) /* begin assembly for a new sub-segment */
378 register segT seg; /* SEG_DATA or SEG_TEXT */
379 register subsegT subseg;
380{
381#ifndef MANY_SEGMENTS
382 know (seg == SEG_DATA || seg == SEG_TEXT || seg == SEG_BSS);
383#endif
384
385 if (seg != now_seg || subseg != now_subseg)
386 { /* we just changed sub-segments */
387 subseg_set_rest (seg, subseg);
388 }
1356d77d 389 mri_common_symbol = NULL;
604633ae
ILT
390}
391
392#else /* BFD_ASSEMBLER */
393
394segT
d025bc7b 395subseg_get (segname, force_new)
604633ae 396 const char *segname;
d025bc7b 397 int force_new;
604633ae
ILT
398{
399 segT secptr;
400 segment_info_type *seginfo;
401 const char *now_seg_name = (now_seg
402 ? bfd_get_section_name (stdoutput, now_seg)
403 : 0);
404
d025bc7b
JL
405 if (!force_new
406 && now_seg_name
604633ae 407 && (now_seg_name == segname
d025bc7b 408 || !strcmp (now_seg_name, segname)))
604633ae
ILT
409 return now_seg;
410
d025bc7b
JL
411 if (!force_new)
412 secptr = bfd_make_section_old_way (stdoutput, segname);
413 else
414 secptr = bfd_make_section_anyway (stdoutput, segname);
415
604633ae
ILT
416 seginfo = seg_info (secptr);
417 if (! seginfo)
418 {
dff770c8
ILT
419 /* Check whether output_section is set first because secptr may
420 be bfd_abs_section_ptr. */
421 if (secptr->output_section != secptr)
422 secptr->output_section = secptr;
604633ae 423 seginfo = (segment_info_type *) xmalloc (sizeof (*seginfo));
3c498933 424 memset ((PTR) seginfo, 0, sizeof (*seginfo));
cc886e3d 425 seginfo->fix_root = NULL;
dff770c8 426 seginfo->fix_tail = NULL;
604633ae 427 seginfo->bfd_section = secptr;
dff770c8
ILT
428 if (secptr == bfd_abs_section_ptr)
429 abs_seg_info = seginfo;
430 else if (secptr == bfd_und_section_ptr)
431 und_seg_info = seginfo;
432 else
433 bfd_set_section_userdata (stdoutput, secptr, (PTR) seginfo);
cc886e3d
SS
434 seginfo->frchainP = NULL;
435 seginfo->lineno_list_head = seginfo->lineno_list_tail = NULL;
436 seginfo->sym = NULL;
437 seginfo->dot = NULL;
604633ae 438 }
d025bc7b
JL
439 return secptr;
440}
441
442segT
443subseg_new (segname, subseg)
444 const char *segname;
445 subsegT subseg;
446{
447 segT secptr;
448 segment_info_type *seginfo;
449
450 secptr = subseg_get (segname, 0);
451 subseg_set_rest (secptr, subseg);
452 seginfo = seg_info (secptr);
453 if (! seginfo->frchainP)
454 seginfo->frchainP = frchain_now;
455 return secptr;
456}
457
458/* Like subseg_new, except a new section is always created, even if
459 a section with that name already exists. */
460segT
461subseg_force_new (segname, subseg)
462 const char *segname;
463 subsegT subseg;
464{
465 segT secptr;
466 segment_info_type *seginfo;
467
468 secptr = subseg_get (segname, 1);
469 subseg_set_rest (secptr, subseg);
470 seginfo = seg_info (secptr);
471 if (! seginfo->frchainP)
472 seginfo->frchainP = frchain_now;
604633ae
ILT
473 return secptr;
474}
475
476void
477subseg_set (secptr, subseg)
478 segT secptr;
479 subsegT subseg;
480{
481 if (! (secptr == now_seg && subseg == now_subseg))
482 subseg_set_rest (secptr, subseg);
1356d77d 483 mri_common_symbol = NULL;
604633ae
ILT
484}
485
cc886e3d
SS
486#ifndef obj_sec_sym_ok_for_reloc
487#define obj_sec_sym_ok_for_reloc(SEC) 0
488#endif
489
dff770c8
ILT
490/* Get the gas information we are storing for a section. */
491
492segment_info_type *
493seg_info (sec)
494 segT sec;
495{
496 if (sec == bfd_abs_section_ptr)
497 return abs_seg_info;
498 else if (sec == bfd_und_section_ptr)
499 return und_seg_info;
500 else
501 return (segment_info_type *) bfd_get_section_userdata (stdoutput, sec);
502}
503
d025bc7b
JL
504symbolS *
505section_symbol (sec)
506 segT sec;
507{
508 segment_info_type *seginfo = seg_info (sec);
cc886e3d 509 symbolS *s;
d025bc7b
JL
510
511 if (seginfo == 0)
512 abort ();
513 if (seginfo->sym)
514 return seginfo->sym;
cc886e3d
SS
515 s = symbol_find (sec->name);
516 if (!s)
d025bc7b 517 {
3c498933
KR
518#ifndef EMIT_SECTION_SYMBOLS
519#define EMIT_SECTION_SYMBOLS 1
520#endif
521
1356d77d 522 if (! EMIT_SECTION_SYMBOLS
3c498933
KR
523#ifdef BFD_ASSEMBLER
524 && symbol_table_frozen
525#endif
526 )
1356d77d 527 /* Here we know it won't be going into the symbol table. */
3c498933 528 s = symbol_create (sec->name, sec, 0, &zero_address_frag);
1356d77d
ILT
529 else
530 s = symbol_new (sec->name, sec, 0, &zero_address_frag);
cc886e3d
SS
531 S_CLEAR_EXTERNAL (s);
532
533 /* Use the BFD section symbol, if possible. */
534 if (obj_sec_sym_ok_for_reloc (sec))
535 s->bsym = sec->symbol;
d025bc7b 536 }
cc886e3d
SS
537 seginfo->sym = s;
538 return s;
d025bc7b
JL
539}
540
604633ae 541#endif /* BFD_ASSEMBLER */
fecd2382 542
8b228fe9 543/* end of subsegs.c */
This page took 0.165976 seconds and 4 git commands to generate.