void md_begin () { char *retval = NULL; unsigned int i = 0; /* initialize hash table */ op_hash = hash_new (); if (op_hash == NULL) as_fatal ("Could not initialize hash table"); /* loop until you see the end of the list */ while (*m88k_opcodes[i].name) { char *name = m88k_opcodes[i].name; /* hash each mnemonic and record its position */ retval = hash_insert (op_hash, name, &m88k_opcodes[i]); if (retval != NULL && *retval != '\0') as_fatal ("Can't hash instruction '%s':%s", m88k_opcodes[i].name, retval); /* skip to next unique mnemonic or end of list */ for (i++; !strcmp (m88k_opcodes[i].name, name); i++) ; } }
/* * frag_grow() * * Try to augment current frag by nchars chars. * If there is no room, close of the current frag with a ".fill 0" * and begin a new frag. Unless the new frag has nchars chars available * do not return. Do not set up any fields of *now_frag. */ void frag_grow( unsigned int nchars) { if(frags.chunk_size == 0) { know(flagseen['n']); as_fatal("with -n a section directive must be seen before assembly " "can begin"); } if ((int)(obstack_room(&frags)) < nchars) { unsigned int n,oldn; long oldc; frag_wane (frag_now); frag_new (0); oldn=(unsigned)-1; oldc=frags.chunk_size; frags.chunk_size=2*nchars; while((int)(n=obstack_room(&frags)) < nchars && n < oldn) { frag_wane(frag_now); frag_new(0); oldn=n; } frags.chunk_size=oldc; } if ((int)(obstack_room(&frags)) < nchars) as_fatal ("Can't extend frag %d. chars", nchars); }
/* This function is called once, at assembler startup time. It should set up all the tables, etc. that the MD part of the assembler will need. */ void md_begin( void) { const char *retval = NULL; int lose = 0; register unsigned int i = 0; op_hash = hash_new(); if (op_hash == NULL) as_fatal("Virtual memory exhausted"); while (i < NUMOPCODES) { const char *name = pa_opcodes[i].name; retval = hash_insert(op_hash, (char *)name, (char *)&pa_opcodes[i]); if(retval != NULL && *retval != '\0') { as_fatal("Internal error: can't hash `%s': %s\n", pa_opcodes[i].name, retval); lose = 1; } ++i; } if (lose) as_fatal ("Broken assembler. No assembly attempted."); }
void input_scrub_include_sb (sb *from, char *position, int is_expansion) { if (macro_nest > max_macro_nest) as_fatal (_("macros nested too deeply")); ++macro_nest; #ifdef md_macro_start if (is_expansion) { md_macro_start (); } #endif next_saved_file = input_scrub_push (position); sb_new (&from_sb); from_sb_is_expansion = is_expansion; if (from->len >= 1 && from->ptr[0] != '\n') { /* Add the sentinel required by read.c. */ sb_add_char (&from_sb, '\n'); } sb_scrub_and_add_sb (&from_sb, from); sb_index = 1; /* These variables are reset by input_scrub_push. Restore them since we are, after all, still at the same point in the file. */ logical_input_line = next_saved_file->logical_input_line; logical_input_file = next_saved_file->logical_input_file; }
void gas_cgen_swap_fixups (int i) { if (i < 0 || i >= MAX_SAVED_FIXUP_CHAINS) { as_fatal ("index into stored_fixups[] out of bounds"); return; } if (num_fixups == 0) gas_cgen_restore_fixups (i); else if (stored_fixups[i].num_fixups_in_chain == 0) gas_cgen_save_fixups (i); else { int tmp; struct fixup tmp_fixup; tmp = stored_fixups[i].num_fixups_in_chain; stored_fixups[i].num_fixups_in_chain = num_fixups; num_fixups = tmp; for (tmp = GAS_CGEN_MAX_FIXUPS; tmp--;) { tmp_fixup = stored_fixups[i].fixup_chain [tmp]; stored_fixups[i].fixup_chain[tmp] = fixups [tmp]; fixups [tmp] = tmp_fixup; } } }
void frag_grow (unsigned int nchars) { if (obstack_room (&frchain_now->frch_obstack) < nchars) { unsigned int n; long oldc; frag_wane (frag_now); frag_new (0); oldc = frchain_now->frch_obstack.chunk_size; /* 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) frchain_now->frch_obstack.chunk_size = 2 * nchars; else frchain_now->frch_obstack.chunk_size = nchars + 0x10000; frchain_now->frch_obstack.chunk_size += SIZEOF_STRUCT_FRAG; if (frchain_now->frch_obstack.chunk_size > 0) while ((n = obstack_room (&frchain_now->frch_obstack)) < nchars && (unsigned long) frchain_now->frch_obstack.chunk_size > nchars) { frag_wane (frag_now); frag_new (0); } frchain_now->frch_obstack.chunk_size = oldc; } if (obstack_room (&frchain_now->frch_obstack) < nchars) as_fatal (_("can't extend frag %u chars"), nchars); }
static void sb_check (sb *ptr, size_t len) { size_t want = ptr->len + len; if (want > ptr->max) { size_t max; want += MALLOC_OVERHEAD + 1; if ((ssize_t) want < 0) as_fatal ("string buffer overflow"); #if GCC_VERSION >= 3004 max = (size_t) 1 << (CHAR_BIT * sizeof (want) - (sizeof (want) <= sizeof (long) ? __builtin_clzl ((long) want) : __builtin_clzll ((long long) want))); #else max = 128; while (want > max) max <<= 1; #endif max -= MALLOC_OVERHEAD + 1; ptr->max = max; ptr->ptr = xrealloc (ptr->ptr, max + 1); } }
/* This function is called once, at assembler startup time. It should set up all the tables, etc. that the MD part of the assembler will need. */ void md_begin() { register char *retval = NULL; int lose = 0; register unsigned int i = 0; op_hash = hash_new(); if (op_hash == NULL) as_fatal("Virtual memory exhausted"); while (i < NUMOPCODES) { const char *name = i860_opcodes[i].name; retval = hash_insert(op_hash, name, &i860_opcodes[i]); if(retval != NULL && *retval != '\0') { fprintf (stderr, "internal error: can't hash `%s': %s\n", i860_opcodes[i].name, retval); lose = 1; } do { if (i860_opcodes[i].match & i860_opcodes[i].lose) { fprintf (stderr, "internal error: losing opcode: `%s' \"%s\"\n", i860_opcodes[i].name, i860_opcodes[i].args); lose = 1; } ++i; } while (i < NUMOPCODES && !strcmp(i860_opcodes[i].name, name)); } if (lose) as_fatal ("Broken assembler. No assembly attempted."); for (i = '0'; i < '8'; ++i) octal[i] = 1; for (i = '0'; i <= '9'; ++i) toHex[i] = i - '0'; for (i = 'a'; i <= 'f'; ++i) toHex[i] = i + 10 - 'a'; for (i = 'A'; i <= 'F'; ++i) toHex[i] = i + 10 - 'A'; }
static void dwcfi_hash_insert (const char *name, struct dwcfi_seg_list *item) { const char *error_string; if ((error_string = hash_jam (dwcfi_hash, name, (char *) item))) as_fatal (_("Inserting \"%s\" into structure table failed: %s"), name, error_string); }
static void tag_insert (const char *name, symbolS *symbolP) { const char *error_string; if ((error_string = hash_jam (tag_hash, name, (char *) symbolP))) as_fatal (_("Inserting \"%s\" into structure table failed: %s"), name, error_string); }
/* * frag_new() * * 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) * fr_var: 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. * * Make a new frag, initialising some components. Link new frag at end * of frchain_now. */ void frag_new( int old_frags_var_max_size) /* Number of chars (already allocated on obstack frags) in variable_length part of frag. */ { register fragS * former_last_fragP; /* char *throw_away_pointer; JF unused */ register frchainS * frchP; long tmp; /* JF */ if(frags.chunk_size == 0) { know(flagseen['n']); as_fatal("with -n a section directive must be seen before assembly " "can begin"); } 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 */ memset(frag_now, '\0', 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; frag_now->fr_next = NULL; } /* frag_new() */
/* * symbol_assign_index() * * Assigns the next index to the given symbol. * * Asserts that the symbol has not been assigned an index yet. * */ void symbol_assign_index( struct symbol *symbolP) { if (symbolP->sy_prev_by_index != NULL) { as_fatal("symbol %s already has an index", symbolP->sy_name); } symbolP->sy_prev_by_index = symbol_lastIndexedP; symbol_lastIndexedP = symbolP; }
static void queue_fixup (int opindex, int opinfo, expressionS *expP) { /* We need to generate a fixup for this expression. */ if (num_fixups >= GAS_CGEN_MAX_FIXUPS) as_fatal (_("too many fixups")); fixups[num_fixups].exp = *expP; fixups[num_fixups].opindex = opindex; fixups[num_fixups].opinfo = opinfo; ++ num_fixups; }
void output_file_create (char *name) { if (name[0] == '-' && name[1] == '\0') as_fatal (_("can't open a bfd on stdout %s"), name); else if (!(stdoutput = bfd_openw (name, TARGET_FORMAT))) { bfd_error_type err = bfd_get_error (); if (err == bfd_error_invalid_target) as_fatal (_("selected target format '%s' unknown"), TARGET_FORMAT); else as_fatal (_("can't create %s: %s"), name, bfd_errmsg (err)); } bfd_set_format (stdoutput, bfd_object); bfd_set_arch_mach (stdoutput, TARGET_ARCH, TARGET_MACH); if (flag_traditional_format) stdoutput->flags |= BFD_TRADITIONAL_FORMAT; }
void gas_cgen_restore_fixups (int i) { if (i < 0 || i >= MAX_SAVED_FIXUP_CHAINS) { as_fatal ("index into stored_fixups[] out of bounds"); return; } num_fixups = stored_fixups[i].num_fixups_in_chain; memcpy (fixups, stored_fixups[i].fixup_chain, (sizeof (stored_fixups[i].fixup_chain[0])) * num_fixups); stored_fixups[i].num_fixups_in_chain = 0; }
/* * symbol_table_insert() * * Die if we can't insert the symbol. * */ void symbol_table_insert( struct symbol *symbolP) { register char * error_string; know( symbolP ); know( symbolP -> sy_name ); if ( * (error_string = hash_jam (sy_hash, symbolP -> sy_name, (char *)symbolP))) { as_fatal( "Inserting \"%s\" into symbol table failed: %s", symbolP -> sy_name, error_string); } }
void gas_cgen_save_fixups (int i) { if (i < 0 || i >= MAX_SAVED_FIXUP_CHAINS) { as_fatal ("index into stored_fixups[] out of bounds"); return; } stored_fixups[i].num_fixups_in_chain = num_fixups; memcpy (stored_fixups[i].fixup_chain, fixups, sizeof (fixups[0]) * num_fixups); num_fixups = 0; }
/* * symbol_table_insert() * * Die if we can't insert the symbol. * */ void symbol_table_insert( struct symbol *symbolP) { const char * error_string; know( symbolP ); know( symbolP -> sy_name ); error_string = hash_jam (sy_hash, symbolP -> sy_name, (char *)symbolP); if (error_string != NULL && error_string[0] != '\0') { as_fatal( "Inserting \"%s\" into symbol table failed: %s", symbolP -> sy_name, error_string); } }
void md_begin () { int i; init_defaults (); insn_hash = hash_new (); if (insn_hash == NULL) as_fatal ("Virtual memory exhausted"); for (i = 0; i < pdp11_num_opcodes; i++) hash_insert (insn_hash, pdp11_opcodes[i].name, (PTR)(pdp11_opcodes + i)); for (i = 0; i < pdp11_num_aliases; i++) hash_insert (insn_hash, pdp11_aliases[i].name, (PTR)(pdp11_aliases + i)); }
void output_file_close (char *filename) { bfd_boolean res; if (stdoutput == NULL) return; /* Close the bfd. */ res = bfd_close (stdoutput); /* Prevent an infinite loop - if the close failed we will call as_fatal which will call xexit() which may call this function again... */ stdoutput = NULL; if (! res) as_fatal (_("can't close %s: %s"), filename, bfd_errmsg (bfd_get_error ())); }
void frag_grow (unsigned int nchars) { if (obstack_room (&frchain_now->frch_obstack) < nchars) { long oldc; long 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 < 0) as_fatal (_("can't extend frag %u chars"), 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; } }
void input_scrub_include_sb (sb *from, char *position, int is_expansion) { int newline; if (macro_nest > max_macro_nest) as_fatal (_("macros nested too deeply")); ++macro_nest; #ifdef md_macro_start if (is_expansion) { md_macro_start (); } #endif next_saved_file = input_scrub_push (position); /* Allocate sufficient space: from->len + optional newline. */ newline = from->len >= 1 && from->ptr[0] != '\n'; sb_build (&from_sb, from->len + newline); from_sb_is_expansion = is_expansion; if (newline) { /* Add the sentinel required by read.c. */ sb_add_char (&from_sb, '\n'); } sb_scrub_and_add_sb (&from_sb, from); /* Make sure the parser looks at defined contents when it scans for e.g. end-of-line at the end of a macro. */ sb_terminate (&from_sb); sb_index = 1; /* These variables are reset by input_scrub_push. Restore them since we are, after all, still at the same point in the file. */ logical_input_line = next_saved_file->logical_input_line; logical_input_file = next_saved_file->logical_input_file; }
static int out_header (asection *sec, expressionS *exp) { symbolS *start_sym; symbolS *end_sym; subseg_set (sec, 0); start_sym = symbol_temp_new_now ();; end_sym = symbol_temp_make (); /* Total length of the information. */ exp->X_op = O_subtract; exp->X_add_symbol = end_sym; exp->X_op_symbol = start_sym; switch (DWARF2_FORMAT (sec)) { case dwarf2_format_32bit: exp->X_add_number = -4; emit_expr (exp, 4); return 4; case dwarf2_format_64bit: exp->X_add_number = -12; out_four (-1); emit_expr (exp, 8); return 8; case dwarf2_format_64bit_irix: exp->X_add_number = -8; emit_expr (exp, 8); return 8; } as_fatal (_("internal error: unknown dwarf2 format")); return 0; }
void obj_som_copyright (int unused ATTRIBUTE_UNUSED) { char *copyright, c; if (copyright_seen) { as_bad (_("Only one .copyright pseudo-op per file!")); ignore_rest_of_line (); return; } SKIP_WHITESPACE (); if (*input_line_pointer == '\"') { copyright = input_line_pointer; ++input_line_pointer; while (is_a_char (next_char_of_string ())) ; c = *input_line_pointer; *input_line_pointer = '\000'; } else { as_bad (_("Expected quoted string")); ignore_rest_of_line (); return; } copyright_seen = 1; if (!bfd_som_attach_aux_hdr (stdoutput, COPYRIGHT_AUX_ID, copyright)) as_fatal (_("attaching copyright header %s: %s"), stdoutput->filename, bfd_errmsg (bfd_get_error ())); *input_line_pointer = c; demand_empty_rest_of_line (); }
void obj_som_version (int unused ATTRIBUTE_UNUSED) { char *version, c; if (version_seen) { as_bad (_("Only one .version pseudo-op per file!")); ignore_rest_of_line (); return; } SKIP_WHITESPACE (); if (*input_line_pointer == '\"') { version = input_line_pointer; ++input_line_pointer; while (is_a_char (next_char_of_string ())) ; c = *input_line_pointer; *input_line_pointer = '\000'; } else { as_bad (_("Expected quoted string")); ignore_rest_of_line (); return; } version_seen = 1; if (!bfd_som_attach_aux_hdr (stdoutput, VERSION_AUX_ID, version)) as_fatal (_("attaching version header %s: %s"), stdoutput->filename, bfd_errmsg (bfd_get_error ())); *input_line_pointer = c; demand_empty_rest_of_line (); }
void add_debug_prefix_map (const char *arg) { debug_prefix_map *map; const char *p; char *o; p = strchr (arg, '='); if (!p) { as_fatal (_("invalid argument '%s' to -fdebug-prefix-map"), arg); return; } map = (struct debug_prefix_map *) xmalloc (sizeof (debug_prefix_map)); o = xstrdup (arg); map->old_prefix = o; map->old_len = p - arg; o[map->old_len] = 0; p++; map->new_prefix = xstrdup (p); map->new_len = strlen (p); map->next = debug_prefix_maps; debug_prefix_maps = map; }
void md_begin (void) { const char *retval = NULL; int i; /* initialize hash table */ op_hash = hash_new (); /* loop until you see the end of the list */ for (i = 0; i < spu_num_opcodes; i++) { /* hash each mnemonic and record its position */ retval = hash_insert (op_hash, spu_opcodes[i].mnemonic, (void *) &spu_opcodes[i]); if (retval != NULL && strcmp (retval, "exists") != 0) as_fatal (_("Can't hash instruction '%s':%s"), spu_opcodes[i].mnemonic, retval); } }
void dwarf2_finish (void) { segT line_seg; struct line_seg *s; segT info_seg; int emit_other_sections = 0; int empty_debug_line = 0; info_seg = bfd_get_section_by_name (stdoutput, ".debug_info"); emit_other_sections = info_seg == NULL || !seg_not_empty_p (info_seg); line_seg = bfd_get_section_by_name (stdoutput, ".debug_line"); empty_debug_line = line_seg == NULL || !seg_not_empty_p (line_seg); /* We can't construct a new debug_line section if we already have one. Give an error. */ if (all_segs && !empty_debug_line) as_fatal ("duplicate .debug_line sections"); if ((!all_segs && emit_other_sections) || (!emit_other_sections && !empty_debug_line)) /* If there is no line information and no non-empty .debug_info section, or if there is both a non-empty .debug_info and a non-empty .debug_line, then we do nothing. */ return; /* Calculate the size of an address for the target machine. */ sizeof_address = DWARF2_ADDR_SIZE (stdoutput); /* Create and switch to the line number section. */ line_seg = subseg_new (".debug_line", 0); bfd_set_section_flags (stdoutput, line_seg, SEC_READONLY | SEC_DEBUGGING); /* For each subsection, chain the debug entries together. */ for (s = all_segs; s; s = s->next) { struct line_subseg *lss = s->head; struct line_entry **ptail = lss->ptail; while ((lss = lss->next) != NULL) { *ptail = lss->head; ptail = lss->ptail; } } out_debug_line (line_seg); /* If this is assembler generated line info, and there is no debug_info already, we need .debug_info and .debug_abbrev sections as well. */ if (emit_other_sections) { segT abbrev_seg; segT aranges_seg; segT ranges_seg; gas_assert (all_segs); info_seg = subseg_new (".debug_info", 0); abbrev_seg = subseg_new (".debug_abbrev", 0); aranges_seg = subseg_new (".debug_aranges", 0); bfd_set_section_flags (stdoutput, info_seg, SEC_READONLY | SEC_DEBUGGING); bfd_set_section_flags (stdoutput, abbrev_seg, SEC_READONLY | SEC_DEBUGGING); bfd_set_section_flags (stdoutput, aranges_seg, SEC_READONLY | SEC_DEBUGGING); record_alignment (aranges_seg, ffs (2 * sizeof_address) - 1); if (all_segs->next == NULL) ranges_seg = NULL; else { ranges_seg = subseg_new (".debug_ranges", 0); bfd_set_section_flags (stdoutput, ranges_seg, SEC_READONLY | SEC_DEBUGGING); record_alignment (ranges_seg, ffs (2 * sizeof_address) - 1); out_debug_ranges (ranges_seg); } out_debug_aranges (aranges_seg, info_seg); out_debug_abbrev (abbrev_seg, info_seg, line_seg); out_debug_info (info_seg, abbrev_seg, line_seg, ranges_seg); } }
/* * section_new() (for non-zerofill sections) switches to a new section, creating * it if needed, and creates a fresh fragment. If it is the current section * nothing happens except checks to make sure the type, attributes and * sizeof_stub are the same. The segment and section names will be trimed to * fit in the section structure and is the responsiblity of the caller to * report errors if they don't. For zerofill sections only the struct frchain * for the section is returned after possibly being created (these section are * never made the current section and no frags are ever touched). * * Globals on input: * frchain_now points to the (possibly none) struct frchain for the current * section. * frag_now points at an incomplete frag for current section. * If frag_now == NULL, then there is no old, incomplete frag, so the old * frag is not closed off. * * Globals on output: * frchain_now points to the (possibly new) struct frchain for this section. * frchain_root updated if needed (for the first section created). * frag_now is set to the last (possibly new) frag in the section. * now_seg is set to the Mach-O section number (frch_nsect field) except * it is not set for section types of S_ZEROFILL or S_THREAD_LOCAL_ZEROFILL. */ frchainS * section_new( char *segname, char *sectname, uint32_t type, uint32_t attributes, uint32_t sizeof_stub) { frchainS *frcP; frchainS **lastPP; uint32_t last_nsect; if(frags.chunk_size == 0) /* * This line is use instead of: * obstack_begin(&frags, 5000); * which the only difference is that frags are allocated on 4 byte * boundaries instead of the default. The problem with the default * is that on some RISC machines the obstack uses 8 (the alignment * of a double after a char in a struct) and then the common use of: * frag_now->fr_fix = obstack_next_free(&frags) - * frag_now->fr_literal; * can get an extra 4 bytes that are not in the frag because of the * 8 byte alignment where only 4 byte alignment for frags are * needed. */ _obstack_begin(&frags, 5000, 4, obstack_chunk_alloc, obstack_chunk_free); /* * Determine if this section has been seen. */ last_nsect = 0; for(frcP = *(lastPP = &frchain_root); frcP != NULL; frcP = *(lastPP = &frcP->frch_next)) { if(strncmp(frcP->frch_section.segname, segname, sizeof(frcP->frch_section.segname)) == 0 && strncmp(frcP->frch_section.sectname, sectname, sizeof(frcP->frch_section.sectname)) == 0) break; last_nsect = frcP->frch_nsect; } /* * If this section has been seen make sure it's type and attributes * for this call are the same as when the section was created. */ if(frcP != NULL) { if((frcP->frch_section.flags & SECTION_TYPE) != type) { as_warn("section type does not match previous section type"); } if(type == S_SYMBOL_STUBS && frcP->frch_section.reserved2 != sizeof_stub) { as_warn("section stub size does not match previous section " "stub size"); } frcP->frch_section.flags |= attributes; } /* * If the current section is the same as for this call there is nothing * more to do. */ if(frcP != NULL && (frchain_now == frcP || type == S_ZEROFILL || type == S_THREAD_LOCAL_ZEROFILL)) { if(type != S_ZEROFILL && type != S_THREAD_LOCAL_ZEROFILL) now_seg = frcP->frch_nsect; return(frcP); } /* * For non-zerofill sections it will be made the current section so deal * with the current frag. */ if(type != S_ZEROFILL && type != S_THREAD_LOCAL_ZEROFILL) { /* * If there is any current frag in the old section close it off. */ if(frag_now != NULL) { frag_now->fr_fix = obstack_next_free(&frags) - frag_now->fr_literal; frag_wane(frag_now); } /* * We must do the obstack_finish(), so the next object we put on * obstack frags will not appear to start at the fr_literal of the * current frag. Also, it ensures that the next object will begin * on a address that is aligned correctly for the engine that runs * the assembler. */ (void)obstack_finish(&frags); } /* * If this section exists since it is not the current section switch to * it by making it the current chain and create a new frag in it. */ if(frcP != NULL) { if(type != S_ZEROFILL && type != S_THREAD_LOCAL_ZEROFILL) now_seg = frcP->frch_nsect; /* * For a zerofill section no frags are created here and since it * exists just return a pointer to the section. */ if((frcP->frch_section.flags & SECTION_TYPE) == S_ZEROFILL || (frcP->frch_section.flags & SECTION_TYPE) == S_THREAD_LOCAL_ZEROFILL) { return(frcP); } else { /* * Make this section the current section. */ frchain_now = frcP; if(type != S_ZEROFILL && type != S_THREAD_LOCAL_ZEROFILL) now_seg = frchain_now->frch_nsect; /* * Make a fresh frag for the section. */ frag_now = (fragS *)obstack_alloc(&frags, SIZEOF_STRUCT_FRAG); memset(frag_now, '\0', SIZEOF_STRUCT_FRAG); frag_now->fr_next = NULL; /* * Append the new frag to the existing frchain. */ frchain_now->frch_last->fr_next = frag_now; frchain_now->frch_last = frag_now; } } else { /* * This section does not exist so create a new frchainS struct fill * it in, link it to the chain */ frcP = (frchainS *)xmalloc(sizeof(frchainS)); memset(frcP, '\0', sizeof(frchainS)); strncpy(frcP->frch_section.segname, segname, sizeof(frcP->frch_section.segname)); strncpy(frcP->frch_section.sectname, sectname, sizeof(frcP->frch_section.sectname)); frcP->frch_section.flags = attributes | type; frcP->frch_section.reserved2 = sizeof_stub; if(last_nsect + 1 > MAX_SECT) as_fatal("too many sections (maximum %d)\n", MAX_SECT); frcP->frch_nsect = last_nsect + 1; if(type != S_ZEROFILL && type != S_THREAD_LOCAL_ZEROFILL) now_seg = frcP->frch_nsect; *lastPP = frcP; /* * For zerofill sections no frag is created here so just return. * For non-zerofill section create the sections new frag and * make the section the current chain. */ if(type == S_ZEROFILL || type == S_THREAD_LOCAL_ZEROFILL) { return(frcP); } else { /* * Make a fresh frag for the new section. */ frag_now = (fragS *)obstack_alloc(&frags, SIZEOF_STRUCT_FRAG); memset(frag_now, '\0', SIZEOF_STRUCT_FRAG); frag_now->fr_next = NULL; /* * Append the new frag to new frchain. */ frcP->frch_root = frag_now; frcP->frch_last = frag_now; /* * Make this section the current section. */ frchain_now = frcP; } } return(frchain_now); }
int atof_generic (/* return pointer to just AFTER number we read. */ char **address_of_string_pointer, /* At most one per number. */ const char *string_of_decimal_marks, const char *string_of_decimal_exponent_marks, FLONUM_TYPE *address_of_generic_floating_point_number) { int return_value; /* 0 means OK. */ char *first_digit; unsigned int number_of_digits_before_decimal; unsigned int number_of_digits_after_decimal; long decimal_exponent; unsigned int number_of_digits_available; char digits_sign_char; /* * Scan the input string, abstracting (1)digits (2)decimal mark (3) exponent. * It would be simpler to modify the string, but we don't; just to be nice * to caller. * We need to know how many digits we have, so we can allocate space for * the digits' value. */ char *p; char c; int seen_significant_digit; #ifdef ASSUME_DECIMAL_MARK_IS_DOT assert (string_of_decimal_marks[0] == '.' && string_of_decimal_marks[1] == 0); #define IS_DECIMAL_MARK(c) ((c) == '.') #else #define IS_DECIMAL_MARK(c) (0 != strchr (string_of_decimal_marks, (c))) #endif first_digit = *address_of_string_pointer; c = *first_digit; if (c == '-' || c == '+') { digits_sign_char = c; first_digit++; } else digits_sign_char = '+'; switch (first_digit[0]) { case 'n': case 'N': if (!strncasecmp ("nan", first_digit, 3)) { address_of_generic_floating_point_number->sign = 0; address_of_generic_floating_point_number->exponent = 0; address_of_generic_floating_point_number->leader = address_of_generic_floating_point_number->low; *address_of_string_pointer = first_digit + 3; return 0; } break; case 'i': case 'I': if (!strncasecmp ("inf", first_digit, 3)) { address_of_generic_floating_point_number->sign = digits_sign_char == '+' ? 'P' : 'N'; address_of_generic_floating_point_number->exponent = 0; address_of_generic_floating_point_number->leader = address_of_generic_floating_point_number->low; first_digit += 3; if (!strncasecmp ("inity", first_digit, 5)) first_digit += 5; *address_of_string_pointer = first_digit; return 0; } break; } number_of_digits_before_decimal = 0; number_of_digits_after_decimal = 0; decimal_exponent = 0; seen_significant_digit = 0; for (p = first_digit; (((c = *p) != '\0') && (!c || !IS_DECIMAL_MARK (c)) && (!c || !strchr (string_of_decimal_exponent_marks, c))); p++) { if (ISDIGIT (c)) { if (seen_significant_digit || c > '0') { ++number_of_digits_before_decimal; seen_significant_digit = 1; } else { first_digit++; } } else { break; /* p -> char after pre-decimal digits. */ } } /* For each digit before decimal mark. */ #ifndef OLD_FLOAT_READS /* Ignore trailing 0's after the decimal point. The original code here * (ifdef'd out) does not do this, and numbers like * 4.29496729600000000000e+09 (2**31) * come out inexact for some reason related to length of the digit * string. */ if (c && IS_DECIMAL_MARK (c)) { unsigned int zeros = 0; /* Length of current string of zeros */ for (p++; (c = *p) && ISDIGIT (c); p++) { if (c == '0') { zeros++; } else { number_of_digits_after_decimal += 1 + zeros; zeros = 0; } } } #else if (c && IS_DECIMAL_MARK (c)) { for (p++; (((c = *p) != '\0') && (!c || !strchr (string_of_decimal_exponent_marks, c))); p++) { if (ISDIGIT (c)) { /* This may be retracted below. */ number_of_digits_after_decimal++; if ( /* seen_significant_digit || */ c > '0') { seen_significant_digit = TRUE; } } else { if (!seen_significant_digit) { number_of_digits_after_decimal = 0; } break; } } /* For each digit after decimal mark. */ } while (number_of_digits_after_decimal && first_digit[number_of_digits_before_decimal + number_of_digits_after_decimal] == '0') --number_of_digits_after_decimal; #endif if (flag_m68k_mri) { while (c == '_') c = *++p; } if (c && strchr (string_of_decimal_exponent_marks, c)) { char digits_exponent_sign_char; c = *++p; if (flag_m68k_mri) { while (c == '_') c = *++p; } if (c && strchr ("+-", c)) { digits_exponent_sign_char = c; c = *++p; } else { digits_exponent_sign_char = '+'; } for (; (c); c = *++p) { if (ISDIGIT (c)) { decimal_exponent = decimal_exponent * 10 + c - '0'; /* * BUG! If we overflow here, we lose! */ } else { break; } } if (digits_exponent_sign_char == '-') { decimal_exponent = -decimal_exponent; } } *address_of_string_pointer = p; number_of_digits_available = number_of_digits_before_decimal + number_of_digits_after_decimal; return_value = 0; if (number_of_digits_available == 0) { address_of_generic_floating_point_number->exponent = 0; /* Not strictly necessary */ address_of_generic_floating_point_number->leader = -1 + address_of_generic_floating_point_number->low; address_of_generic_floating_point_number->sign = digits_sign_char; /* We have just concocted (+/-)0.0E0 */ } else { int count; /* Number of useful digits left to scan. */ LITTLENUM_TYPE *digits_binary_low; unsigned int precision; unsigned int maximum_useful_digits; unsigned int number_of_digits_to_use; unsigned int more_than_enough_bits_for_digits; unsigned int more_than_enough_littlenums_for_digits; unsigned int size_of_digits_in_littlenums; unsigned int size_of_digits_in_chars; FLONUM_TYPE power_of_10_flonum; FLONUM_TYPE digits_flonum; precision = (address_of_generic_floating_point_number->high - address_of_generic_floating_point_number->low + 1); /* Number of destination littlenums. */ /* Includes guard bits (two littlenums worth) */ maximum_useful_digits = (((precision - 2)) * ( (LITTLENUM_NUMBER_OF_BITS)) * 1000000 / 3321928) + 2; /* 2 :: guard digits. */ if (number_of_digits_available > maximum_useful_digits) { number_of_digits_to_use = maximum_useful_digits; } else { number_of_digits_to_use = number_of_digits_available; } /* Cast these to SIGNED LONG first, otherwise, on systems with LONG wider than INT (such as Alpha OSF/1), unsignedness may cause unexpected results. */ decimal_exponent += ((long) number_of_digits_before_decimal - (long) number_of_digits_to_use); more_than_enough_bits_for_digits = (number_of_digits_to_use * 3321928 / 1000000 + 1); more_than_enough_littlenums_for_digits = (more_than_enough_bits_for_digits / LITTLENUM_NUMBER_OF_BITS) + 2; /* Compute (digits) part. In "12.34E56" this is the "1234" part. Arithmetic is exact here. If no digits are supplied then this part is a 0 valued binary integer. Allocate room to build up the binary number as littlenums. We want this memory to disappear when we leave this function. Assume no alignment problems => (room for n objects) == n * (room for 1 object). */ size_of_digits_in_littlenums = more_than_enough_littlenums_for_digits; size_of_digits_in_chars = size_of_digits_in_littlenums * sizeof (LITTLENUM_TYPE); digits_binary_low = (LITTLENUM_TYPE *) alloca (size_of_digits_in_chars); memset ((char *) digits_binary_low, '\0', size_of_digits_in_chars); /* Digits_binary_low[] is allocated and zeroed. */ /* * Parse the decimal digits as if * digits_low was in the units position. * Emit a binary number into digits_binary_low[]. * * Use a large-precision version of: * (((1st-digit) * 10 + 2nd-digit) * 10 + 3rd-digit ...) * 10 + last-digit */ for (p = first_digit, count = number_of_digits_to_use; count; p++, --count) { c = *p; if (ISDIGIT (c)) { /* * Multiply by 10. Assume can never overflow. * Add this digit to digits_binary_low[]. */ long carry; LITTLENUM_TYPE *littlenum_pointer; LITTLENUM_TYPE *littlenum_limit; littlenum_limit = digits_binary_low + more_than_enough_littlenums_for_digits - 1; carry = c - '0'; /* char -> binary */ for (littlenum_pointer = digits_binary_low; littlenum_pointer <= littlenum_limit; littlenum_pointer++) { long work; work = carry + 10 * (long) (*littlenum_pointer); *littlenum_pointer = work & LITTLENUM_MASK; carry = work >> LITTLENUM_NUMBER_OF_BITS; } if (carry != 0) { /* * We have a GROSS internal error. * This should never happen. */ as_fatal (_("failed sanity check")); } } else { ++count; /* '.' doesn't alter digits used count. */ } } /* * Digits_binary_low[] properly encodes the value of the digits. * Forget about any high-order littlenums that are 0. */ while (digits_binary_low[size_of_digits_in_littlenums - 1] == 0 && size_of_digits_in_littlenums >= 2) size_of_digits_in_littlenums--; digits_flonum.low = digits_binary_low; digits_flonum.high = digits_binary_low + size_of_digits_in_littlenums - 1; digits_flonum.leader = digits_flonum.high; digits_flonum.exponent = 0; /* * The value of digits_flonum . sign should not be important. * We have already decided the output's sign. * We trust that the sign won't influence the other parts of the number! * So we give it a value for these reasons: * (1) courtesy to humans reading/debugging * these numbers so they don't get excited about strange values * (2) in future there may be more meaning attached to sign, * and what was * harmless noise may become disruptive, ill-conditioned (or worse) * input. */ digits_flonum.sign = '+'; { /* * Compute the mantssa (& exponent) of the power of 10. * If successful, then multiply the power of 10 by the digits * giving return_binary_mantissa and return_binary_exponent. */ LITTLENUM_TYPE *power_binary_low; int decimal_exponent_is_negative; /* This refers to the "-56" in "12.34E-56". */ /* FALSE: decimal_exponent is positive (or 0) */ /* TRUE: decimal_exponent is negative */ FLONUM_TYPE temporary_flonum; LITTLENUM_TYPE *temporary_binary_low; unsigned int size_of_power_in_littlenums; unsigned int size_of_power_in_chars; size_of_power_in_littlenums = precision; /* Precision has a built-in fudge factor so we get a few guard bits. */ decimal_exponent_is_negative = decimal_exponent < 0; if (decimal_exponent_is_negative) { decimal_exponent = -decimal_exponent; } /* From now on: the decimal exponent is > 0. Its sign is separate. */ size_of_power_in_chars = size_of_power_in_littlenums * sizeof (LITTLENUM_TYPE) + 2; power_binary_low = (LITTLENUM_TYPE *) alloca (size_of_power_in_chars); temporary_binary_low = (LITTLENUM_TYPE *) alloca (size_of_power_in_chars); memset ((char *) power_binary_low, '\0', size_of_power_in_chars); *power_binary_low = 1; power_of_10_flonum.exponent = 0; power_of_10_flonum.low = power_binary_low; power_of_10_flonum.leader = power_binary_low; power_of_10_flonum.high = power_binary_low + size_of_power_in_littlenums - 1; power_of_10_flonum.sign = '+'; temporary_flonum.low = temporary_binary_low; temporary_flonum.high = temporary_binary_low + size_of_power_in_littlenums - 1; /* * (power) == 1. * Space for temporary_flonum allocated. */ /* * ... * * WHILE more bits * DO find next bit (with place value) * multiply into power mantissa * OD */ { int place_number_limit; /* Any 10^(2^n) whose "n" exceeds this */ /* value will fall off the end of */ /* flonum_XXXX_powers_of_ten[]. */ int place_number; const FLONUM_TYPE *multiplicand; /* -> 10^(2^n) */ place_number_limit = table_size_of_flonum_powers_of_ten; multiplicand = (decimal_exponent_is_negative ? flonum_negative_powers_of_ten : flonum_positive_powers_of_ten); for (place_number = 1;/* Place value of this bit of exponent. */ decimal_exponent;/* Quit when no more 1 bits in exponent. */ decimal_exponent >>= 1, place_number++) { if (decimal_exponent & 1) { if (place_number > place_number_limit) { /* The decimal exponent has a magnitude so great that our tables can't help us fragment it. Although this routine is in error because it can't imagine a number that big, signal an error as if it is the user's fault for presenting such a big number. */ return_value = ERROR_EXPONENT_OVERFLOW; /* quit out of loop gracefully */ decimal_exponent = 0; } else { #ifdef TRACE printf ("before multiply, place_number = %d., power_of_10_flonum:\n", place_number); flonum_print (&power_of_10_flonum); (void) putchar ('\n'); #endif #ifdef TRACE printf ("multiplier:\n"); flonum_print (multiplicand + place_number); (void) putchar ('\n'); #endif flonum_multip (multiplicand + place_number, &power_of_10_flonum, &temporary_flonum); #ifdef TRACE printf ("after multiply:\n"); flonum_print (&temporary_flonum); (void) putchar ('\n'); #endif flonum_copy (&temporary_flonum, &power_of_10_flonum); #ifdef TRACE printf ("after copy:\n"); flonum_print (&power_of_10_flonum); (void) putchar ('\n'); #endif } /* If this bit of decimal_exponent was computable.*/ } /* If this bit of decimal_exponent was set. */ } /* For each bit of binary representation of exponent */ #ifdef TRACE printf ("after computing power_of_10_flonum:\n"); flonum_print (&power_of_10_flonum); (void) putchar ('\n'); #endif } } /* * power_of_10_flonum is power of ten in binary (mantissa) , (exponent). * It may be the number 1, in which case we don't NEED to multiply. * * Multiply (decimal digits) by power_of_10_flonum. */ flonum_multip (&power_of_10_flonum, &digits_flonum, address_of_generic_floating_point_number); /* Assert sign of the number we made is '+'. */ address_of_generic_floating_point_number->sign = digits_sign_char; }