- register fragS * former_last_fragP;
- /* char *throw_away_pointer; JF unused */
- register frchainS * frchP;
- long tmp; /* JF */
-
- frag_now->fr_fix = (char *) (obstack_next_free (&frags)) -
- (frag_now->fr_literal) - old_frags_var_max_size;
- /* Fix up old frag's fr_fix. */
-
- obstack_finish (&frags);
- /* This will align the obstack so the */
- /* next struct we allocate on it will */
- /* begin at a correct boundary. */
- frchP = frchain_now;
- know (frchP);
- former_last_fragP = frchP->frch_last;
- know (former_last_fragP);
- know (former_last_fragP == frag_now);
- obstack_blank (&frags, SIZEOF_STRUCT_FRAG);
- /* We expect this will begin at a correct */
- /* boundary for a struct. */
- tmp=obstack_alignment_mask(&frags);
- obstack_alignment_mask(&frags)=0; /* Turn off alignment */
- /* If we ever hit a machine
- where strings must be
- aligned, we Lose Big */
- frag_now=(fragS *)obstack_finish(&frags);
- obstack_alignment_mask(&frags)=tmp; /* Restore alignment */
-
- /* Just in case we don't get zero'd bytes */
- bzero(frag_now, SIZEOF_STRUCT_FRAG);
-
- /* obstack_unaligned_done (&frags, &frag_now); */
- /* know (frags.obstack_c_next_free == frag_now->fr_literal); */
- /* Generally, frag_now->points to an */
- /* address rounded up to next alignment. */
- /* However, characters will add to obstack */
- /* frags IMMEDIATELY after the struct frag, */
- /* even if they are not starting at an */
- /* alignment address. */
- former_last_fragP->fr_next = frag_now;
- frchP->frch_last = frag_now;
-
+ if (obstack_room (&frchain_now->frch_obstack) < nchars)
+ {
+ size_t oldc;
+ size_t newc;
+
+ /* Try to allocate a bit more than needed right now. But don't do
+ this if we would waste too much memory. Especially necessary
+ for extremely big (like 2GB initialized) frags. */
+ if (nchars < 0x10000)
+ newc = 2 * nchars;
+ else
+ newc = nchars + 0x10000;
+ newc += SIZEOF_STRUCT_FRAG;
+
+ /* Check for possible overflow. */
+ if (newc < nchars)
+ as_fatal (ngettext ("can't extend frag %lu char",
+ "can't extend frag %lu chars",
+ (unsigned long) nchars),
+ (unsigned long) nchars);
+
+ /* Force to allocate at least NEWC bytes, but not less than the
+ default. */
+ oldc = obstack_chunk_size (&frchain_now->frch_obstack);
+ if (newc > oldc)
+ obstack_chunk_size (&frchain_now->frch_obstack) = newc;
+
+ while (obstack_room (&frchain_now->frch_obstack) < nchars)
+ {
+ /* Not enough room in this frag. Close it and start a new one.
+ This must be done in a loop because the created frag may not
+ be big enough if the current obstack chunk is used. */
+ frag_wane (frag_now);
+ frag_new (0);
+ }
+
+ /* Restore the old chunk size. */
+ obstack_chunk_size (&frchain_now->frch_obstack) = oldc;
+ }
+}
+\f
+/* Call this to close off a completed frag, and start up a new (empty)
+ frag, in the same subsegment as the old frag.
+ [frchain_now remains the same but frag_now is updated.]
+ Because this calculates the correct value of fr_fix by
+ looking at the obstack 'frags', it needs to know how many
+ characters at the end of the old frag belong to the maximal
+ variable part; The rest must belong to fr_fix.
+ It doesn't actually set up the old frag's fr_var. You may have
+ set fr_var == 1, but allocated 10 chars to the end of the frag;
+ In this case you pass old_frags_var_max_size == 10.
+ In fact, you may use fr_var for something totally unrelated to the
+ size of the variable part of the frag; None of the generic frag
+ handling code makes use of fr_var.
+
+ Make a new frag, initialising some components. Link new frag at end
+ of frchain_now. */
+
+void
+frag_new (size_t old_frags_var_max_size
+ /* Number of chars (already allocated on obstack frags) in
+ variable_length part of frag. */)
+{
+ fragS *former_last_fragP;
+ frchainS *frchP;
+
+ gas_assert (frchain_now->frch_last == frag_now);
+
+ /* Fix up old frag's fr_fix. */
+ frag_now->fr_fix = frag_now_fix_octets ();
+ gas_assert (frag_now->fr_fix >= old_frags_var_max_size);
+ frag_now->fr_fix -= old_frags_var_max_size;
+ /* Make sure its type is valid. */
+ gas_assert (frag_now->fr_type != 0);
+
+ /* This will align the obstack so the next struct we allocate on it
+ will begin at a correct boundary. */
+ obstack_finish (&frchain_now->frch_obstack);
+ frchP = frchain_now;
+ know (frchP);
+ former_last_fragP = frchP->frch_last;
+ gas_assert (former_last_fragP != 0);
+ gas_assert (former_last_fragP == frag_now);
+ frag_now = frag_alloc (&frchP->frch_obstack);
+
+ frag_now->fr_file = as_where (&frag_now->fr_line);
+
+ /* Generally, frag_now->points to an address rounded up to next
+ alignment. However, characters will add to obstack frags
+ IMMEDIATELY after the struct frag, even if they are not starting
+ at an alignment address. */
+ former_last_fragP->fr_next = frag_now;
+ frchP->frch_last = frag_now;
+