#define MASK_CHAR (0xFF)
#define MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT (16)
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "stuff/rnd.h"
#include "stuff/arch.h"
#include "stuff/best_arch.h"
#include "as.h"
#include "flonum.h"
#include "struc-symbol.h"
#include "expr.h"
#include "read.h"
#include "hash.h"
#include "obstack.h"
#include "md.h"
#include "symbols.h"
#include "sections.h"
#include "input-scrub.h"
#include "input-file.h"
#include "hex_value.h"
#include "messages.h"
#include "xmalloc.h"
#include "app.h"
#if defined(I386) && defined(ARCH64)
#include "i386.h"
#endif
#include "dwarf2dbg.h"
char *input_line_pointer = NULL;
char *buffer_limit = NULL;
#define TARGET_BYTES_BIG_ENDIAN 0
int target_big_endian = TARGET_BYTES_BIG_ENDIAN;
#ifndef PPC
const
#endif
char lex_type[256] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 3,
0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3
};
static
#ifndef PPC
const
#endif
char is_end_of_line_tab[256] = {
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
#if defined(M88K) || defined(PPC) || defined(HPPA)
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
#else
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
#endif
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
char is_end_of_line(int c) { return is_end_of_line_tab[c & 0xFF]; }
#define MAX_IF_DEPTH 20
typedef enum {
no_cond,
if_cond,
elseif_cond,
else_cond
}cond_type;
struct cond_state {
cond_type the_cond;
int cond_met;
int ignore;
};
typedef struct cond_state cond_stateS;
static cond_stateS the_cond_state = {no_cond, FALSE, FALSE};
static cond_stateS last_states[MAX_IF_DEPTH];
static int if_depth = 0;
#define MAX_MACRO_DEPTH 20
static int macro_depth = 0;
static struct hash_control
*ma_hash = NULL;
static struct obstack macros;
static char *macro_name = NULL;
static int count_lines = TRUE;
static int macros_on = TRUE;
static void expand_macro(char *macro_contents);
static void macro_begin(void);
static FILE *dump_fp = NULL;
static void write_macro(const char *string, PTR value);
static void write_symbol(const char *string, PTR value);
static void parse_a_buffer(char *buffer);
#ifdef PPC
static void ppcasm_parse_a_buffer(char *buffer);
#endif
static void parse_line_comment(char **buffer);
static segT get_segmented_expression(expressionS *expP);
static void pseudo_op_begin(void);
#ifdef PPC
static void ppcasm_pseudo_op_begin(void);
#endif
static void stab(uintptr_t what);
static char get_absolute_expression_and_terminator(int32_t *val_pointer);
static char *demand_copy_string(int *lenP);
static int is_it_end_of_statement(void);
static void equals(char *sym_name);
static int next_char_of_string(void);
#ifdef M68K
#define BIGNUM_BEGIN_SIZE (16)
static char *bignum_low;
static char *bignum_limit;
static char *bignum_high;
static void grow_bignum(void);
#endif
uint32_t text_nsect = 0;
struct type_name {
char *name;
unsigned type;
};
static struct type_name type_names[] = {
{ "regular", S_REGULAR },
{ "cstring_literals", S_CSTRING_LITERALS },
{ "4byte_literals", S_4BYTE_LITERALS },
{ "8byte_literals", S_8BYTE_LITERALS },
{ "16byte_literals", S_16BYTE_LITERALS },
{ "literal_pointers", S_LITERAL_POINTERS },
#if !(defined(I386) && defined(ARCH64))
{ "non_lazy_symbol_pointers", S_NON_LAZY_SYMBOL_POINTERS },
{ "lazy_symbol_pointers", S_LAZY_SYMBOL_POINTERS },
{ "symbol_stubs", S_SYMBOL_STUBS },
#endif
{ "mod_init_funcs", S_MOD_INIT_FUNC_POINTERS },
{ "mod_term_funcs", S_MOD_TERM_FUNC_POINTERS },
{ "coalesced", S_COALESCED },
{ "interposing", S_INTERPOSING },
{ "thread_local_regular", S_THREAD_LOCAL_REGULAR },
{ "thread_local_variables", S_THREAD_LOCAL_VARIABLES },
{ "thread_local_init_function_pointers",
S_THREAD_LOCAL_INIT_FUNCTION_POINTERS },
{ NULL, 0 }
};
struct attribute_name {
char *name;
unsigned attribute;
};
static struct attribute_name attribute_names[] = {
{ "none", 0 },
{ "pure_instructions", S_ATTR_PURE_INSTRUCTIONS },
{ "no_toc", S_ATTR_NO_TOC },
{ "strip_static_syms", S_ATTR_STRIP_STATIC_SYMS },
{ "no_dead_strip", S_ATTR_NO_DEAD_STRIP },
{ "live_support", S_ATTR_LIVE_SUPPORT },
{ "self_modifying_code", S_ATTR_SELF_MODIFYING_CODE },
{ "debug", S_ATTR_DEBUG },
{ NULL, 0 }
};
struct builtin_section {
char *directive;
char *segname;
char *sectname;
uint32_t flags;
uint32_t default_align;
uint32_t sizeof_stub;
};
static const struct builtin_section builtin_sections[] = {
{ "text", "__TEXT", "__text", S_ATTR_PURE_INSTRUCTIONS },
{ "const", "__TEXT", "__const" },
{ "static_const", "__TEXT", "__static_const" },
{ "cstring", "__TEXT", "__cstring", S_CSTRING_LITERALS },
{ "literal4", "__TEXT", "__literal4", S_4BYTE_LITERALS, 2 },
{ "literal8", "__TEXT", "__literal8", S_8BYTE_LITERALS, 3 },
{ "literal16", "__TEXT", "__literal16", S_16BYTE_LITERALS, 4 },
{ "constructor", "__TEXT", "__constructor" },
{ "destructor", "__TEXT", "__destructor" },
{ "fvmlib_init0", "__TEXT", "__fvmlib_init0" },
{ "fvmlib_init1", "__TEXT", "__fvmlib_init1" },
#if !(defined(I386) && defined(ARCH64))
{ "symbol_stub", "__TEXT", "__symbol_stub",
S_SYMBOL_STUBS | S_ATTR_PURE_INSTRUCTIONS,
#if defined(M68K)
1, 20
#endif
#if defined(I386)
0, 16
#endif
#if defined(HPPA)
2, 28
#endif
#if defined(SPARC)
2, 32
#endif
#if defined(PPC)
2, 20
#endif
},
#endif
#if !(defined(I386) && defined(ARCH64))
{ "picsymbol_stub", "__TEXT", "__picsymbol_stub",
S_SYMBOL_STUBS | S_ATTR_PURE_INSTRUCTIONS,
#if defined(M68K)
1, 24
#endif
#if defined(I386)
0, 26
#endif
#if defined(HPPA)
2, 32
#endif
#if defined(SPARC)
2, 60
#endif
#if defined(PPC)
2, 36
#endif
},
#endif
#if !(defined(I386) && defined(ARCH64))
{ "non_lazy_symbol_pointer","__DATA","__nl_symbol_ptr",
S_NON_LAZY_SYMBOL_POINTERS, 2 },
{ "lazy_symbol_pointer", "__DATA", "__la_symbol_ptr",
S_LAZY_SYMBOL_POINTERS, 2 },
#endif
{ "mod_init_func", "__DATA", "__mod_init_func",
S_MOD_INIT_FUNC_POINTERS, 2 },
{ "mod_term_func", "__DATA", "__mod_term_func",
S_MOD_TERM_FUNC_POINTERS, 2 },
{ "dyld", "__DATA", "__dyld" },
{ "data", "__DATA", "__data" },
{ "static_data", "__DATA", "__static_data" },
{ "const_data", "__DATA", "__const" },
{ "tdata", "__DATA", "__thread_data",
S_THREAD_LOCAL_REGULAR },
{ "tlv", "__DATA", "__thread_vars",
S_THREAD_LOCAL_VARIABLES },
{ "thread_init_func", "__DATA", "__thread_init",
S_THREAD_LOCAL_INIT_FUNCTION_POINTERS },
{ "objc_class", "__OBJC", "__class", S_ATTR_NO_DEAD_STRIP },
{ "objc_meta_class", "__OBJC", "__meta_class", S_ATTR_NO_DEAD_STRIP },
{ "objc_string_object", "__OBJC", "__string_object", S_ATTR_NO_DEAD_STRIP},
{ "objc_protocol", "__OBJC", "__protocol", S_ATTR_NO_DEAD_STRIP },
{ "objc_cat_cls_meth", "__OBJC", "__cat_cls_meth", S_ATTR_NO_DEAD_STRIP },
{ "objc_cat_inst_meth", "__OBJC", "__cat_inst_meth", S_ATTR_NO_DEAD_STRIP},
{ "objc_cls_meth", "__OBJC", "__cls_meth", S_ATTR_NO_DEAD_STRIP },
{ "objc_inst_meth", "__OBJC", "__inst_meth", S_ATTR_NO_DEAD_STRIP },
{ "objc_message_refs", "__OBJC", "__message_refs",
S_LITERAL_POINTERS | S_ATTR_NO_DEAD_STRIP, 2},
{ "objc_cls_refs", "__OBJC", "__cls_refs",
S_LITERAL_POINTERS | S_ATTR_NO_DEAD_STRIP, 2},
{ "objc_class_names", "__TEXT", "__cstring", S_CSTRING_LITERALS },
{ "objc_module_info", "__OBJC", "__module_info", S_ATTR_NO_DEAD_STRIP },
{ "objc_symbols", "__OBJC", "__symbols", S_ATTR_NO_DEAD_STRIP },
{ "objc_category", "__OBJC", "__category", S_ATTR_NO_DEAD_STRIP },
{ "objc_meth_var_types", "__TEXT", "__cstring", S_CSTRING_LITERALS },
{ "objc_class_vars", "__OBJC", "__class_vars", S_ATTR_NO_DEAD_STRIP },
{ "objc_instance_vars", "__OBJC", "__instance_vars", S_ATTR_NO_DEAD_STRIP},
{ "objc_meth_var_names", "__TEXT", "__cstring", S_CSTRING_LITERALS },
{ "objc_selector_strs", "__OBJC", "__selector_strs", S_CSTRING_LITERALS },
{ 0 }
};
static struct hash_control *po_hash = NULL;
#ifdef PPC
static struct hash_control *ppcasm_po_hash = NULL;
#endif
#if !defined(I860)
static void s_align(int value, int bytes_p);
static void s_align_bytes(uintptr_t arg);
static void s_align_ptwo(uintptr_t arg);
static void s_org(uintptr_t value);
#endif
static void s_private_extern(uintptr_t value);
#if !(defined(I386) && defined(ARCH64))
static void s_indirect_symbol(uintptr_t value);
#endif
static void s_abort(uintptr_t value);
static void s_comm(uintptr_t value);
static void s_desc(uintptr_t value);
static void s_fill(uintptr_t value);
static void s_lcomm(uintptr_t value);
static void s_lsym(uintptr_t value);
static void s_set(uintptr_t value);
static void s_reference(uintptr_t value);
static void s_lazy_reference(uintptr_t value);
static void s_weak_reference(uintptr_t value);
static void s_weak_definition(uintptr_t value);
static void s_weak_def_can_be_hidden(uintptr_t value);
static void s_no_dead_strip(uintptr_t value);
static void s_symbol_resolver(uintptr_t value);
static void s_include(uintptr_t value);
static void s_dump(uintptr_t value);
static void s_load(uintptr_t value);
static void s_if(uintptr_t value);
static void s_elseif(uintptr_t value);
static void s_else(uintptr_t value);
static void s_endif(uintptr_t value);
static void s_macros_on(uintptr_t value);
static void s_macros_off(uintptr_t value);
static void s_section(uintptr_t value);
static void s_zerofill(uintptr_t value);
static uint32_t s_builtin_section(const struct builtin_section *s);
static void s_subsections_via_symbols(uintptr_t value);
static void s_machine(uintptr_t value);
static void s_secure_log_unique(uintptr_t value);
static void s_secure_log_reset(uintptr_t value);
static void s_inlineasm(uintptr_t value);
static void s_leb128(uintptr_t sign);
static void s_incbin(uintptr_t value);
static void s_data_region(uintptr_t value);
static void s_end_data_region(uintptr_t value);
#ifdef PPC
static void s_ppcasm_end(uintptr_t value);
#endif
static const pseudo_typeS pseudo_table[] = {
#if !defined(I860)
{ "align", s_align_ptwo, 1 },
{ "align32", s_align_ptwo, 4 },
{ "p2align", s_align_ptwo, 1 },
{ "p2alignw", s_align_ptwo, 2 },
{ "p2alignl", s_align_ptwo, 4 },
{ "balign", s_align_bytes, 1 },
{ "balignw", s_align_bytes, 2 },
{ "balignl", s_align_bytes, 4 },
{ "org", s_org, 0 },
#endif
#ifndef M88K
{ "abs", s_abs, 0 },
#endif
{ "private_extern", s_private_extern, 0},
#if !(defined(I386) && defined(ARCH64))
{ "indirect_symbol", s_indirect_symbol, 0},
#endif
{ "abort", s_abort, 0 },
{ "ascii", stringer, 0 },
{ "asciz", stringer, 1 },
{ "byte", cons, 1 },
{ "comm", s_comm, 0 },
{ "desc", s_desc, 0 },
{ "double", float_cons, 'd' },
{ "appfile", s_app_file, 0 },
{ "fill", s_fill, 0 },
{ "globl", s_globl, 0 },
{ "lcomm", s_lcomm, 0 },
{ "line", s_line, 0 },
{ "long", cons, 4 },
{ "quad", cons, 8 },
{ "lsym", s_lsym, 0 },
{ "section", s_section, 0 },
{ "zerofill", s_zerofill, S_ZEROFILL },
{ "tbss", s_zerofill, S_THREAD_LOCAL_ZEROFILL },
{ "secure_log_unique",s_secure_log_unique, 0 },
{ "secure_log_reset",s_secure_log_reset, 0 },
{ "set", s_set, 0 },
{ "short", cons, 2 },
{ "single", float_cons, 'f' },
{ "space", s_space, 0 },
{ "sleb128", s_leb128, 1},
{ "uleb128", s_leb128, 0},
{ "stabd", stab, 'd' },
{ "stabn", stab, 'n' },
{ "stabs", stab, 's' },
{ "debug_note", stab, 's' },
{ "reference",s_reference, 0 },
{ "lazy_reference",s_lazy_reference, 0 },
{ "weak_reference",s_weak_reference, 0 },
{ "weak_definition",s_weak_definition, 0 },
{ "weak_def_can_be_hidden",s_weak_def_can_be_hidden, 0 },
{ "no_dead_strip",s_no_dead_strip, 0 },
{ "symbol_resolver",s_symbol_resolver, 0 },
{ "include", s_include, 0 },
{ "macro", s_macro, 0 },
{ "endmacro", s_endmacro, 0 },
{ "endm", s_endmacro, 0 },
{ "macros_on",s_macros_on, 0 },
{ "macros_off",s_macros_off, 0 },
{ "if", s_if, 0 },
{ "elseif", s_elseif, 0 },
{ "else", s_else, 0 },
{ "endif", s_endif, 0 },
{ "dump", s_dump, 0 },
{ "load", s_load, 0 },
{ "subsections_via_symbols", s_subsections_via_symbols, 0 },
{ "machine", s_machine, 0 },
{ "inlineasmstart", s_inlineasm, 1 },
{ "inlineasmend", s_inlineasm, 0 },
{ "incbin", s_incbin, 0 },
{ "data_region", s_data_region, 0 },
{ "end_data_region", s_end_data_region, 0 },
{ NULL }
};
#ifdef PPC
static const pseudo_typeS ppcasm_pseudo_table[] = {
{ "include", s_include, 0 },
{ "end", s_ppcasm_end, 0 },
{ NULL }
};
#endif
static enum bool s_secure_log_used = FALSE;
void
read_begin(
void)
{
pseudo_op_begin();
macro_begin();
obstack_begin(¬es, 5000);
#ifdef M68K
bignum_low = xmalloc((int32_t)BIGNUM_BEGIN_SIZE);
bignum_limit = bignum_low + BIGNUM_BEGIN_SIZE;
#endif
}
#ifdef PPC
void
ppcasm_read_begin(
void)
{
is_end_of_line_tab['\r'] = 1;
is_end_of_line_tab['@'] = 0;
is_end_of_line_tab[':'] = 0;
ppcasm_pseudo_op_begin();
}
#endif
static
void
pseudo_op_begin(
void)
{
const char *errtxt;
const pseudo_typeS *pop;
uint32_t i;
pseudo_typeS *sections_pseudo_table;
po_hash = hash_new();
errtxt = NULL;
for(pop = pseudo_table;
pop->poc_name && (!errtxt || *errtxt == '\0');
pop++)
errtxt = hash_insert(po_hash, pop->poc_name, (char *)pop);
for(pop = md_pseudo_table;
pop->poc_name && (!errtxt || *errtxt == '\0');
pop++)
errtxt = hash_insert(po_hash, pop->poc_name, (char *)pop);
for(i = 0; builtin_sections[i].directive != NULL; i++)
;
sections_pseudo_table = xmalloc((i + 1) * sizeof(pseudo_typeS));
for(i = 0; builtin_sections[i].directive != NULL; i++){
sections_pseudo_table[i].poc_name = builtin_sections[i].directive;
sections_pseudo_table[i].poc_handler =
(void (*)(uintptr_t))s_builtin_section;
sections_pseudo_table[i].poc_val = (uintptr_t)(builtin_sections +i);
}
sections_pseudo_table[i].poc_name = NULL;
for(pop = (const pseudo_typeS *)sections_pseudo_table;
pop->poc_name && (!errtxt || *errtxt == '\0');
pop++)
errtxt = hash_insert(po_hash, pop->poc_name, (char *)pop);
if(errtxt != NULL && *errtxt != '\0'){
as_fatal("error constructing pseudo-op table (%s)", errtxt);
}
}
#ifdef PPC
static
void
ppcasm_pseudo_op_begin(
void)
{
const char *errtxt;
char *uppercase;
const pseudo_typeS *pop;
uint32_t len, i;
ppcasm_po_hash = hash_new();
errtxt = NULL;
for(pop = ppcasm_pseudo_table; pop->poc_name != NULL; pop++){
errtxt = hash_insert(ppcasm_po_hash, pop->poc_name, (char *)pop);
if(errtxt != NULL && *errtxt != '\0')
as_fatal("error constructing pseudo-op table (%s)", errtxt);
len = strlen(pop->poc_name);
uppercase = xmalloc(len);
strcpy(uppercase, pop->poc_name);
for(i = 0; i < len; i++)
uppercase[i] = toupper(uppercase[i]);
errtxt = hash_insert(ppcasm_po_hash, uppercase, (char *)pop);
if(errtxt != NULL && *errtxt != '\0')
as_fatal("error constructing pseudo-op table (%s)", errtxt);
}
}
#endif
void
read_a_source_file(
char *buffer)
{
cond_stateS starting_cond_state;
short starting_if_depth;
symbolS *symbolP;
starting_cond_state = the_cond_state;
starting_if_depth = if_depth;
if(doing_include == FALSE){
if(flagseen['n'] == FALSE)
text_nsect = s_builtin_section(builtin_sections);
if(flagseen['g']){
symbolP = symbol_new(
physical_input_file,
100 ,
text_nsect,
0,
obstack_next_free(&frags) - frag_now->fr_literal,
frag_now);
symbolP = symbol_new(
"int:t1=r1;-2147483648;2147483647;",
128 ,
0,0,0,
&zero_address_frag);
symbolP = symbol_new(
"char:t2=r2;0;127;",
128 ,
0,0,0,
&zero_address_frag);
symbolP = symbol_new(
"void:t3=3",
128 ,
0,0,0,
&zero_address_frag);
}
if(debug_type == DEBUG_DWARF2){
dwarf2_file(physical_input_file, ++dwarf2_file_number);
}
}
else{
if(flagseen['g'] && frchain_now->frch_nsect == text_nsect){
symbolP = symbol_new(
physical_input_file,
132 ,
text_nsect,
0,
obstack_next_free(&frags) - frag_now->fr_literal,
frag_now);
}
}
while((buffer_limit = input_scrub_next_buffer(&buffer)) != NULL){
#ifdef PPC
if(flagseen[(int)'p'] == TRUE)
ppcasm_parse_a_buffer(buffer);
else
#endif
parse_a_buffer(buffer);
}
if(the_cond_state.the_cond != starting_cond_state.the_cond ||
the_cond_state.ignore != starting_cond_state.ignore||
if_depth != starting_if_depth)
as_bad("file contains unmatched .ifs or .elses");
if(macro_name != NULL)
as_bad("file contains unmatched .macro and .endmacro for: %s",
macro_name);
if(doing_include == FALSE){
if(flagseen['n'] == FALSE)
text_nsect = s_builtin_section(builtin_sections);
if(flagseen['g']){
(void)symbol_new(
"",
100 ,
text_nsect,
0,
obstack_next_free(&frags) - frag_now->fr_literal,
frag_now);
}
}
}
static
void
parse_a_buffer(
char *buffer)
{
char c;
char *s;
char after_name;
char *after_name_pointer;
char end_of_line;
char *start_of_line;
pseudo_typeS *pop;
char *the_macro;
int temp;
char *backup;
know(buffer_limit[-1] == '\n');
input_line_pointer = buffer;
while(input_line_pointer < buffer_limit){
start_of_line = input_line_pointer;
if(count_lines == TRUE && input_line_pointer[-1] == '\n')
bump_line_counters ();
c = *input_line_pointer;
input_line_pointer++;
if(c == '\t' || c == ' ' || c=='\f'){
c = *input_line_pointer;
input_line_pointer++;
}
know(c != ' ');
if(is_name_beginner(c) || c == '"'){
if( c == '"')
s = input_line_pointer--;
else
s = --input_line_pointer;
after_name = get_symbol_end();
after_name_pointer = input_line_pointer;
if(*s == '.' &&
(after_name != ':' &&
after_name != '=' &&
!((after_name == ' ' || after_name == '\t') &&
input_line_pointer[1] == '=') ) ){
pop = (pseudo_typeS *)hash_find(po_hash, s+1);
*input_line_pointer = after_name;
if(after_name == ' ' || after_name == '\t')
input_line_pointer++;
if(the_cond_state.ignore){
if(pop != NULL &&
( (pop->poc_handler == s_if) ||
(pop->poc_handler == s_elseif) ||
(pop->poc_handler == s_else) ||
(pop->poc_handler == s_endif) ) )
(*pop->poc_handler)(pop->poc_val);
else
totally_ignore_line();
}
else if(macro_name){
if(pop != NULL &&
pop->poc_handler == s_endmacro)
(*pop->poc_handler)(pop->poc_val);
else
add_to_macro_definition(start_of_line);
}
else{
if(pop != NULL)
(*pop->poc_handler)(pop->poc_val);
else{
after_name = *after_name_pointer;
*after_name_pointer = '\0';
if(macros_on == TRUE &&
(the_macro = hash_find(ma_hash, s)) != NULL){
*after_name_pointer = after_name;
expand_macro(the_macro);
}
else{
as_bad ("Unknown pseudo-op: %s", s);
*after_name_pointer = after_name;
ignore_rest_of_line();
}
}
}
continue;
}
if(the_cond_state.ignore){
*input_line_pointer = after_name;
totally_ignore_line();
}
else if(macro_name != NULL){
*input_line_pointer = after_name;
add_to_macro_definition(start_of_line);
}
else if(after_name == ':'){
colon(s, 0);
#ifdef I860
if(input_line_pointer[1] == ':'){
struct symbol *symbolP;
symbolP = symbol_find_or_make(s);
symbolP->sy_type |= N_EXT;
*input_line_pointer = ':';
input_line_pointer++;
}
#endif
*input_line_pointer = ':';
input_line_pointer++;
}
else if(after_name == '=' ||
((after_name == ' ' || after_name == '\t') &&
input_line_pointer[1] == '=')){
equals(s);
demand_empty_rest_of_line();
}
else if(macros_on == TRUE &&
(the_macro = hash_find(ma_hash, s)) != NULL){
*input_line_pointer = after_name;
expand_macro(the_macro);
}
else{
*input_line_pointer = after_name;
while(is_end_of_line(*input_line_pointer) == 0)
input_line_pointer++;
end_of_line = *input_line_pointer;
*input_line_pointer = '\0';
md_assemble(s);
*input_line_pointer = end_of_line;
input_line_pointer++;
}
continue;
}
if(is_end_of_line(c))
continue;
if(the_cond_state.ignore){
totally_ignore_line();
continue;
}
if(macro_name != NULL){
add_to_macro_definition(start_of_line);
continue;
}
if(isdigit(c)){
backup = input_line_pointer;
temp = c - '0';
while(isdigit(*input_line_pointer))
{
temp = (temp * 10) + *input_line_pointer - '0';
++input_line_pointer;
}
if(*input_line_pointer++ == ':'){
local_colon(temp);
continue;
}
input_line_pointer = backup;
}
if(c != '\0' && strchr(md_line_comment_chars, c) != NULL){
parse_line_comment(&buffer);
continue;
}
as_bad("Junk character %d (%c).", c, c);
ignore_rest_of_line();
}
}
#ifdef PPC
static
void
ppcasm_parse_a_buffer(
char *buffer)
{
char c;
char *s;
char after_name;
char *after_name_pointer;
char end_of_line;
char *start_of_line;
pseudo_typeS *pop;
know(buffer_limit[-1] == '\n');
input_line_pointer = buffer;
while(input_line_pointer < buffer_limit){
start_of_line = input_line_pointer;
if(count_lines == TRUE && input_line_pointer[-1] == '\n')
bump_line_counters ();
c = *input_line_pointer;
if(is_name_beginner(c)){
s = input_line_pointer;
while(is_part_of_name(c)){
input_line_pointer++;
c = *input_line_pointer;
}
after_name = c;
after_name_pointer = input_line_pointer;
*after_name_pointer = '\0';
colon(s, 0);
*after_name_pointer = after_name;
if(*input_line_pointer == ' ')
input_line_pointer++;
if(c == ':'){
input_line_pointer++;
c = *input_line_pointer;
}
}
if(*input_line_pointer == ' ')
input_line_pointer++;
c = *input_line_pointer;
if(is_name_beginner(c)){
s = input_line_pointer;
while(is_part_of_name(c)){
input_line_pointer++;
c = *input_line_pointer;
}
after_name = c;
after_name_pointer = input_line_pointer;
*after_name_pointer = '\0';
pop = (pseudo_typeS *)hash_find(ppcasm_po_hash, s);
*input_line_pointer = after_name;
if(*input_line_pointer == ' ')
input_line_pointer++;
if(pop != NULL){
(*pop->poc_handler)(pop->poc_val);
continue;
}
else{
while(is_end_of_line(*input_line_pointer) == 0)
input_line_pointer++;
end_of_line = *input_line_pointer;
*input_line_pointer = '\0';
md_assemble(s);
*input_line_pointer = end_of_line;
input_line_pointer++;
continue;
}
}
if(is_end_of_line(c)){
input_line_pointer++;
continue;
}
as_bad("Junk character %d (%c).", c, c);
ignore_rest_of_line();
}
}
#endif
static
void
parse_line_comment(
char **buffer)
{
char *s;
char *ends;
char *new_buf;
char *new_tmp;
int new_length;
char *tmp_buf;
char *old_input_line_pointer;
char *old_buffer_limit;
know(preprocess == FALSE);
s = input_line_pointer;
if(strncmp(s,"APP\n",4) != 0)
return;
if(count_lines == TRUE)
bump_line_counters();
s += sizeof("APP\n") - 1;
ends = strstr(s, "#NO_APP\n");
tmp_buf = NULL;
if(ends == NULL){
int tmp_len;
int num;
tmp_len = buffer_limit - s;
tmp_buf = xmalloc(tmp_len);
memcpy(tmp_buf, s, tmp_len);
do{
buffer_limit = input_scrub_next_buffer(buffer);
if(buffer_limit == NULL)
break;
ends = strstr(*buffer, "#NO_APP\n");
if(ends != NULL)
num = ends - *buffer;
else
num = buffer_limit - *buffer;
tmp_buf = xrealloc(tmp_buf, tmp_len + num);
memcpy(tmp_buf + tmp_len, *buffer, num);
tmp_len += num;
}while(ends == NULL);
if(ends != NULL)
input_line_pointer = ends + sizeof("#NO_APP\n") - 1;
else{
input_line_pointer = *buffer;
buffer_limit = *buffer;
}
s = tmp_buf;
ends = s + tmp_len;
}
else{
input_line_pointer = ends + sizeof("#NO_APP\n") - 1;
}
new_length = 100;
new_buf = xmalloc(new_length);
new_tmp = new_buf;
*new_tmp++ = '\n';
scrub_string = s;
scrub_last_string = ends;
for(;;){
int c;
c = do_scrub_next_char_from_string();
if(c == EOF)
break;
*new_tmp++ = c;
if(new_tmp == new_buf + new_length){
new_buf = xrealloc(new_buf, new_length + 100);
new_tmp = new_buf + new_length;
new_length += 100;
}
}
*new_tmp = '\n';
if(tmp_buf != NULL)
free(tmp_buf);
old_input_line_pointer = input_line_pointer;
old_buffer_limit = buffer_limit;
input_line_pointer = new_buf;
buffer_limit = new_tmp;
#ifdef PPC
if(flagseen[(int)'p'] == TRUE)
ppcasm_parse_a_buffer(new_buf);
else
#endif
parse_a_buffer(new_buf);
free(new_buf);
if(count_lines == TRUE)
bump_line_counters();
input_line_pointer = old_input_line_pointer;
buffer_limit = old_buffer_limit;
return;
}
static
void
s_abort(
uintptr_t value)
{
char *p;
p = input_line_pointer;
while(is_end_of_line(*p) == FALSE)
p++;
*p = '\0';
as_fatal(".abort %s detected. Assembly stopping.", input_line_pointer);
}
#if !defined(I860)
static
void
s_align_bytes(
uintptr_t arg)
{
s_align(arg, 1);
}
static
void
s_align_ptwo(
uintptr_t arg)
{
s_align(arg, 0);
}
static
void
s_align(
int fill_size,
int bytes_p)
{
int power_of_2_alignment, byte_alignment, i;
int32_t temp_fill, fill_specified, max_bytes_to_fill;
char fill[4];
if(fill_size != 1 && fill_size != 2 && fill_size != 4)
as_bad("Internal error, s_align() called with bad fill_size %d",
fill_size);
power_of_2_alignment = 0;
if(bytes_p == 0){
power_of_2_alignment = get_absolute_expression();
}
else{
byte_alignment = get_absolute_expression();
if(byte_alignment != 0){
for(i = 0; (byte_alignment & 1) == 0; i++)
byte_alignment >>= 1;
if(byte_alignment != 1)
as_bad("alignment not a power of 2");
power_of_2_alignment = i;
}
}
#define MAX_ALIGNMENT (15)
if(power_of_2_alignment > MAX_ALIGNMENT)
as_warn("Alignment too large: %d. assumed.",
power_of_2_alignment = MAX_ALIGNMENT);
else if(power_of_2_alignment < 0){
as_warn("Alignment negative. 0 assumed.");
power_of_2_alignment = 0;
}
temp_fill = 0;
fill_specified = 0;
max_bytes_to_fill = 0;
if(*input_line_pointer == ','){
input_line_pointer ++;
if(*input_line_pointer != ','){
temp_fill = get_absolute_expression ();
fill_specified = 1;
}
if(*input_line_pointer == ','){
input_line_pointer ++;
max_bytes_to_fill = get_absolute_expression ();
}
}
if(fill_specified == 0 &&
((frchain_now->frch_section.flags & S_ATTR_SOME_INSTRUCTIONS) ==
S_ATTR_SOME_INSTRUCTIONS ||
(frchain_now->frch_section.flags & S_ATTR_PURE_INSTRUCTIONS) ==
S_ATTR_PURE_INSTRUCTIONS) ){
#ifdef M68K
if(power_of_2_alignment >= 1){
temp_fill = 0x4e71;
fill_size = 2;
}
#endif
#ifdef I386
temp_fill = 0x90;
fill_size = 1;
#endif
#ifdef HPPA
if(power_of_2_alignment >= 2){
temp_fill = 0x08000240;
fill_size = 4;
}
#endif
#ifdef SPARC
if(power_of_2_alignment >= 2){
temp_fill = 0x01000000;
fill_size = 4;
}
#endif
#ifdef M88K
if(power_of_2_alignment >= 2){
temp_fill = 0xf4005800;
fill_size = 4;
}
#endif
#ifdef PPC
if(power_of_2_alignment >= 2){
temp_fill = 0x60000000;
fill_size = 4;
}
#endif
#ifdef ARM
if(power_of_2_alignment >= 1){
extern int thumb_mode;
if(thumb_mode){
if(archflag_cpusubtype == CPU_SUBTYPE_ARM_V7 ||
archflag_cpusubtype == CPU_SUBTYPE_ARM_V7F ||
archflag_cpusubtype == CPU_SUBTYPE_ARM_V7K){
temp_fill = 0xbf00;
fill_size = 2;
}
else{
temp_fill = 0x46c0;
fill_size = 2;
}
}
else if(power_of_2_alignment >= 2){
temp_fill = 0xe1a00000;
fill_size = 4;
}
}
#endif
;
}
md_number_to_chars(fill, temp_fill, fill_size);
if(power_of_2_alignment != 0)
frag_align(power_of_2_alignment, fill, fill_size,max_bytes_to_fill);
if(max_bytes_to_fill == 0 &&
frchain_now->frch_section.align <
(uint32_t)power_of_2_alignment)
frchain_now->frch_section.align = power_of_2_alignment;
demand_empty_rest_of_line();
}
#endif
static
void
s_comm(
uintptr_t value)
{
char *name;
char c;
char *p;
signed_target_addr_t temp;
symbolS *symbolP;
int power_of_2_alignment;
if(*input_line_pointer == '"')
name = input_line_pointer + 1;
else
name = input_line_pointer;
c = get_symbol_end();
p = input_line_pointer;
*p = c;
SKIP_WHITESPACE();
if(*input_line_pointer != ','){
as_bad("Expected comma after symbol-name");
ignore_rest_of_line();
return;
}
input_line_pointer++;
if((temp = get_absolute_expression ()) < 0){
as_bad(".COMMon length (" TA_DFMT ".) <0! Ignored.", temp);
ignore_rest_of_line();
return;
}
power_of_2_alignment = 0;
#define MAX_ALIGNMENT (15)
if(*input_line_pointer == ','){
input_line_pointer++;
power_of_2_alignment = get_absolute_expression();
if(power_of_2_alignment > MAX_ALIGNMENT)
as_warn("Alignment too large: %d. assumed.",
power_of_2_alignment = MAX_ALIGNMENT);
else if(power_of_2_alignment < 0){
as_warn("Alignment negative. 0 assumed.");
power_of_2_alignment = 0;
}
}
*p = 0;
symbolP = symbol_find_or_make(name);
*p = c;
if((symbolP->sy_type & N_TYPE) != N_UNDF ||
symbolP->sy_other != 0 ||
(symbolP->sy_desc & ~N_NO_DEAD_STRIP) != 0) {
as_bad("Ignoring attempt to re-define symbol");
ignore_rest_of_line();
return;
}
if(symbolP->sy_value != 0){
if(symbolP->sy_value != (uint32_t)temp)
as_bad("Length of .comm \"%s\" is already " TA_DFMT ". Not "
"changed to " TA_DFMT ".", symbolP->sy_name,
symbolP->sy_value, temp);
}
else{
symbolP -> sy_value = temp;
symbolP -> sy_type |= N_EXT;
SET_COMM_ALIGN(symbolP->sy_desc, power_of_2_alignment);
}
know(symbolP->sy_frag == &zero_address_frag);
demand_empty_rest_of_line();
}
static
void
s_desc(
uintptr_t value)
{
char *name;
char c;
char *p;
symbolS *symbolP;
int temp;
if(*input_line_pointer == '"')
name = input_line_pointer + 1;
else
name = input_line_pointer;
c = get_symbol_end();
p = input_line_pointer;
symbolP = symbol_table_lookup(name);
*p = c;
SKIP_WHITESPACE();
if(*input_line_pointer != ','){
*p = 0;
as_bad("Expected comma after name \"%s\"", name);
*p = c;
ignore_rest_of_line();
}
else{
input_line_pointer++;
temp = get_absolute_expression();
*p = 0;
symbolP = symbol_find_or_make(name);
*p = c;
symbolP->sy_desc = temp;
}
demand_empty_rest_of_line();
}
void
s_app_file(
uintptr_t value)
{
char *s;
int length;
struct symbol *symbolP;
if((s = demand_copy_string(&length))){
SKIP_WHITESPACE();
if(*input_line_pointer >= '0' && *input_line_pointer <= '9'){
while(*input_line_pointer >= '0' &&
*input_line_pointer <= '9')
input_line_pointer++;
}
new_logical_line(s, -1);
demand_empty_rest_of_line();
if(flagseen['g'] && frchain_now->frch_nsect == text_nsect){
symbolP = symbol_new(
logical_input_file,
132 ,
text_nsect,
0,
obstack_next_free(&frags) - frag_now->fr_literal,
frag_now);
}
}
}
static
void
s_fill(
uintptr_t value)
{
int32_t temp_repeat;
int32_t temp_size;
int32_t temp_fill;
char *p;
if(get_absolute_expression_and_terminator(&temp_repeat) != ','){
input_line_pointer--;
as_bad("Expect comma after rep-size in .fill");
ignore_rest_of_line();
return;
}
if(get_absolute_expression_and_terminator(&temp_size) != ','){
input_line_pointer--;
as_bad("Expected comma after size in .fill");
ignore_rest_of_line();
return;
}
#define BSD_FILL_SIZE_CROCK_8 (8)
if(temp_size > BSD_FILL_SIZE_CROCK_8){
as_bad(".fill size clamped to %d.", BSD_FILL_SIZE_CROCK_8);
temp_size = BSD_FILL_SIZE_CROCK_8 ;
}
if(temp_size < 0){
as_bad("Size negative: .fill ignored.");
temp_size = 0;
}
else if(temp_size != 0 &&
temp_size != 1 &&
temp_size != 2 &&
temp_size != 4 &&
temp_size != 8){
as_bad(".fill size must be 0,1,2,4 or 8, .fill ignored");
temp_size = 0;
}
else if(temp_repeat <= 0){
as_bad(".fill repeat <= 0, .fill ignored");
temp_size = 0;
}
temp_fill = get_absolute_expression();
if(temp_size != 0){
p = frag_var(rs_fill,
(int)temp_size,
(int)temp_size,
(relax_substateT)0,
(symbolS *)0,
temp_repeat,
(char *)0);
memset(p, '\0', (int)temp_size);
#define BSD_FILL_SIZE_CROCK_4 (4)
md_number_to_chars(p,
temp_fill,
temp_size > BSD_FILL_SIZE_CROCK_4 ?
BSD_FILL_SIZE_CROCK_4 : (int)temp_size);
}
demand_empty_rest_of_line();
}
void
s_globl(
uintptr_t value)
{
char *name;
int c;
symbolS *symbolP;
do{
if(*input_line_pointer == '"')
name = input_line_pointer + 1;
else
name = input_line_pointer;
c = get_symbol_end();
symbolP = symbol_find_or_make(name);
*input_line_pointer = c;
SKIP_WHITESPACE();
symbolP->sy_type |= N_EXT;
if(c == ','){
input_line_pointer++;
SKIP_WHITESPACE();
if(*input_line_pointer == '\n')
c = '\n';
}
}while(c == ',');
demand_empty_rest_of_line();
}
static
void
s_private_extern(
uintptr_t value)
{
char *name;
int c;
symbolS *symbolP;
do{
if(*input_line_pointer == '"')
name = input_line_pointer + 1;
else
name = input_line_pointer;
c = get_symbol_end();
symbolP = symbol_find_or_make(name);
*input_line_pointer = c;
SKIP_WHITESPACE();
symbolP->sy_type |= N_EXT;
symbolP->sy_type |= N_PEXT;
if(c == ','){
input_line_pointer++;
SKIP_WHITESPACE();
if(*input_line_pointer == '\n')
c = '\n';
}
}while(c == ',');
demand_empty_rest_of_line();
}
#if !(defined(I386) && defined(ARCH64))
static
void
s_indirect_symbol(
uintptr_t value)
{
char *name;
int c;
uint32_t section_type;
if(!flagseen['k'])
as_fatal("incompatible feature used: .indirect_symbol (must "
"specify \"-dynamic\" to be used)");
if(frchain_now == NULL){
know(flagseen['n']);
as_fatal("with -n a section directive must be seen before assembly "
"can begin");
}
section_type = frchain_now->frch_section.flags & SECTION_TYPE;
if(section_type != S_NON_LAZY_SYMBOL_POINTERS &&
section_type != S_LAZY_SYMBOL_POINTERS &&
section_type != S_SYMBOL_STUBS){
as_bad("indirect symbol not in a symbol pointer or stub section, "
".indirect_symbol ignored");
ignore_rest_of_line();
return;
}
if(*input_line_pointer == '"')
name = input_line_pointer + 1;
else
name = input_line_pointer;
c = get_symbol_end();
indirect_symbol_new(name,
frag_now,
obstack_next_free(&frags) - frag_now->fr_literal);
*input_line_pointer = c;
demand_empty_rest_of_line();
}
#endif
static
void
s_lcomm(
uintptr_t value)
{
char *name;
char c;
char *p;
signed_target_addr_t size;
symbolS *symbolP;
int align;
static frchainS *bss = NULL;
if(*input_line_pointer == '"')
name = input_line_pointer + 1;
else
name = input_line_pointer;
c = get_symbol_end();
p = input_line_pointer;
*p = c;
SKIP_WHITESPACE();
if(*input_line_pointer != ','){
as_bad("Expected comma after name");
ignore_rest_of_line();
return;
}
input_line_pointer ++;
if((size = get_absolute_expression()) < 0){
as_bad("BSS length (" TA_DFMT ".) <0! Ignored.", size);
ignore_rest_of_line();
return;
}
#define MAX_ALIGNMENT (15)
align = 0;
if(*input_line_pointer == ','){
input_line_pointer++;
align = get_absolute_expression();
if(align > MAX_ALIGNMENT){
as_warn("Alignment too large: %d. assumed.", MAX_ALIGNMENT);
align = MAX_ALIGNMENT;
}
else if(align < 0){
as_warn("Alignment negative. 0 assumed.");
align = 0;
}
}
*p = 0;
symbolP = symbol_find_or_make(name);
*p = c;
if((symbolP->sy_type & N_TYPE) == N_UNDF && symbolP->sy_value == 0){
if(bss == NULL){
bss = section_new(SEG_DATA, SECT_BSS, S_ZEROFILL, 0, 0);
bss->frch_root = xmalloc(SIZEOF_STRUCT_FRAG);
memset(bss->frch_root, '\0', SIZEOF_STRUCT_FRAG);
bss->frch_last = bss->frch_root;
}
bss->frch_root->fr_address = rnd(bss->frch_root->fr_address,
1 << align);
symbolP->sy_value = bss->frch_root->fr_address;
symbolP->sy_type = N_SECT;
symbolP->sy_other = bss->frch_nsect;
symbolP->sy_frag = bss->frch_root;
bss->frch_root->fr_address += size;
if(bss->frch_section.align < (uint32_t)align)
bss->frch_section.align = align;
}
else
as_bad("Ignoring attempt to re-define symbol.");
demand_empty_rest_of_line();
}
void
s_line(
uintptr_t value)
{
new_logical_line((char *)NULL, (int)(get_absolute_expression()) - 1);
demand_empty_rest_of_line();
}
static
void
s_lsym(
uintptr_t value)
{
char *name;
char c;
char *p;
segT segment;
expressionS exp;
symbolS *symbolP;
if(*input_line_pointer == '"')
name = input_line_pointer + 1;
else
name = input_line_pointer;
c = get_symbol_end();
p = input_line_pointer;
*p = c;
SKIP_WHITESPACE();
if(*input_line_pointer != ','){
*p = 0;
as_bad("Expected comma after name \"%s\"", name);
*p = c;
ignore_rest_of_line();
return;
}
input_line_pointer++;
segment = expression(&exp);
if(segment != SEG_ABSOLUTE && segment != SEG_SECT){
as_bad("Bad expression: %s", seg_name[(int)segment]);
ignore_rest_of_line();
return;
}
know(segment == SEG_ABSOLUTE || segment == SEG_SECT);
*p = 0;
if(segment == SEG_SECT)
symbolP = symbol_new(name,
N_SECT,
frchain_now->frch_nsect,
0,
(valueT)(exp.X_add_number),
&zero_address_frag);
else
symbolP = symbol_new(name,
N_ABS,
0,
0,
(valueT)(exp.X_add_number),
&zero_address_frag);
*p = c;
demand_empty_rest_of_line();
}
#if !defined(I860)
static
void
s_org(
uintptr_t value)
{
segT segment;
expressionS exp;
int32_t temp_fill;
char *p;
segment = get_known_segmented_expression(&exp);
if(*input_line_pointer == ','){
input_line_pointer ++;
temp_fill = get_absolute_expression ();
}
else
temp_fill = 0;
if((segment != SEG_SECT ||
exp.X_add_symbol->sy_other != frchain_now->frch_nsect) &&
segment != SEG_ABSOLUTE)
as_bad("Illegal expression. current section assumed.");
p = frag_var(rs_org,
1,
1,
(relax_substateT)0,
exp.X_add_symbol,
exp.X_add_number,
(char *)0);
*p = temp_fill;
demand_empty_rest_of_line();
}
#endif
static
void
s_set(
uintptr_t value)
{
char *name;
char delim;
char *end_name;
symbolS *symbolP;
if( * input_line_pointer == '"')
name = input_line_pointer + 1;
else
name = input_line_pointer;
delim = get_symbol_end();
end_name = input_line_pointer;
*end_name = delim;
SKIP_WHITESPACE();
if(*input_line_pointer != ','){
*end_name = 0;
as_bad("Expected comma after name \"%s\"", name);
*end_name = delim;
ignore_rest_of_line();
return;
}
input_line_pointer++;
*end_name = 0;
if(name[0] == '.' && name[1] == '\0'){
segT segment;
expressionS exp;
char *ptr;
segment = get_known_segmented_expression(&exp);
if((segment != SEG_SECT ||
exp.X_add_symbol->sy_other != frchain_now->frch_nsect) &&
segment != SEG_ABSOLUTE)
as_bad("Illegal expression. current section assumed.");
ptr = frag_var(rs_org,
1,
1,
(relax_substateT)0,
exp.X_add_symbol,
exp.X_add_number,
(char *)0);
*ptr = 0;
*end_name = delim;
return;
}
symbolP = symbol_find_or_make(name);
symbolP->sy_desc |= N_NO_DEAD_STRIP;
*end_name = delim;
pseudo_set(symbolP);
demand_empty_rest_of_line();
}
void
s_abs(
uintptr_t value)
{
char *name;
char c;
char *p;
segT segment;
expressionS exp;
symbolS *symbolP;
if(*input_line_pointer == '"')
name = input_line_pointer + 1;
else
name = input_line_pointer;
c = get_symbol_end();
p = input_line_pointer;
*p = c;
SKIP_WHITESPACE();
if(*input_line_pointer != ','){
*p = 0;
as_bad("Expected comma after name \"%s\"", name);
*p = c;
ignore_rest_of_line();
return;
}
input_line_pointer++;
*p = 0;
segment = expression(&exp);
symbolP = symbol_find_or_make(name);
symbolP->sy_type = N_ABS;
symbolP->sy_other = 0;
symbolP->sy_frag = &zero_address_frag;
if(segment == SEG_ABSOLUTE)
symbolP->sy_value = 1;
else
symbolP->sy_value = 0;
*p = c;
totally_ignore_line();
}
void
s_space(
uintptr_t value)
{
int32_t temp_repeat;
int32_t temp_fill;
char *p;
if(get_absolute_expression_and_terminator(&temp_repeat) == ','){
temp_fill = get_absolute_expression();
}
else{
input_line_pointer--;
temp_fill = 0;
}
if(temp_repeat <= 0){
as_bad("Repeat < 0, .space ignored");
ignore_rest_of_line();
return;
}
p = frag_var(rs_fill,
1,
1,
(relax_substateT)0,
(symbolS *)0,
temp_repeat,
(char *)0);
*p = temp_fill;
demand_empty_rest_of_line();
}
static
uint32_t
s_builtin_section(
const struct builtin_section *s)
{
frchainS *frcP;
if(!flagseen['k']){
if((s->flags & SECTION_TYPE) == S_NON_LAZY_SYMBOL_POINTERS ||
(s->flags & SECTION_TYPE) == S_LAZY_SYMBOL_POINTERS ||
(s->flags & SECTION_TYPE) == S_SYMBOL_STUBS ||
#if !(defined(I386) && defined(ARCH64))
(s->flags & SECTION_TYPE) == S_MOD_INIT_FUNC_POINTERS ||
(s->flags & SECTION_TYPE) == S_MOD_TERM_FUNC_POINTERS ||
#endif
(s->flags & SECTION_ATTRIBUTES & ~S_ATTR_PURE_INSTRUCTIONS) != 0)
as_fatal("incompatible feature used: directive .%s (must "
"specify \"-dynamic\" to be used)", s->directive);
}
frcP = section_new(s->segname, s->sectname,
s->flags & SECTION_TYPE,
s->flags & SECTION_ATTRIBUTES,
s->sizeof_stub);
if(frcP->frch_section.align < s->default_align)
frcP->frch_section.align = s->default_align;
return(frcP->frch_nsect);
}
static
void
s_section(
uintptr_t value)
{
char *segname, *sectname, *typename;
char c, d, e, *p, *q, *r;
struct type_name *type_name;
uint32_t type, attribute;
section_t s;
frchainS *frcP;
uint32_t sizeof_stub;
struct attribute_name *attribute_name;
char *attributename, *sizeof_stub_name, f, g, *t, *u, *endp;
segname = input_line_pointer;
do{
c = *input_line_pointer++ ;
}while(c != ',' && c != '\0' && c != '\n');
if(c != ','){
as_bad("Expected comma after segment-name");
ignore_rest_of_line();
return;
}
p = input_line_pointer - 1;
SKIP_WHITESPACE();
sectname = input_line_pointer;
do{
d = *input_line_pointer++ ;
}while(d != ',' && d != '\0' && d != '\n');
if(p + 1 == input_line_pointer){
as_bad("Expected section-name after comma");
ignore_rest_of_line();
return;
}
q = input_line_pointer - 1;
*p = 0;
if(strlen(segname) > sizeof(s.segname)){
as_bad("segment-name: %s too long (maximum %ld characters)",
segname, sizeof(s.segname));
ignore_rest_of_line();
*p = c;
return;
}
*q = 0;
if(strlen(sectname) > sizeof(s.sectname)){
as_bad("section-name: %s too long (maximum %ld characters)",
sectname, sizeof(s.sectname));
ignore_rest_of_line();
return;
}
type = 0;
type_name = type_names;
attribute = 0;
attribute_name = attribute_names;
sizeof_stub = 0;
if(d == ','){
typename = input_line_pointer;
do{
e = *input_line_pointer++ ;
}
while(e != ',' && !(is_end_of_line(e)));
r = input_line_pointer - 1;
*r = 0;
for(type_name = type_names; type_name->name != NULL; type_name++)
if(strcmp(type_name->name, typename) == 0)
break;
if(type_name->name == NULL){
as_bad("unknown section type: %s", typename);
ignore_rest_of_line();
return;
}
*r = e;
type = type_name->type;
if(e == ','){
do{
attributename = input_line_pointer;
do{
f = *input_line_pointer++ ;
}while(f != ',' && f != '+' && !(is_end_of_line(f)));
t = input_line_pointer - 1;
*t = 0;
for(attribute_name = attribute_names;
attribute_name->name != NULL;
attribute_name++)
if(strcmp(attribute_name->name, attributename) == 0)
break;
if(attribute_name->name == NULL){
as_bad("unknown section attribute: %s", attributename);
ignore_rest_of_line();
return;
}
*t = f;
attribute |= attribute_name->attribute;
}while(f == '+');
if(type == S_SYMBOL_STUBS){
if(f == ','){
sizeof_stub_name = input_line_pointer;
do{
g = *input_line_pointer++ ;
}while(!(is_end_of_line(g)));
u = input_line_pointer - 1;
*u = 0;
sizeof_stub = strtoul(sizeof_stub_name, &endp, 0);
if(*endp != '\0'){
as_bad("size of stub section: %s not a proper "
"number", sizeof_stub_name);
ignore_rest_of_line();
return;
}
*u = g;
}
else{
as_bad("missing size of stub section (%s,%s)", segname,
sectname);
ignore_rest_of_line();
return;
}
}
}
else if(type == S_SYMBOL_STUBS){
as_bad("missing size of stub section (%s,%s)", segname,
sectname);
ignore_rest_of_line();
return;
}
}
input_line_pointer--;
if(!flagseen['k']){
if(type == S_NON_LAZY_SYMBOL_POINTERS ||
type == S_LAZY_SYMBOL_POINTERS ||
type == S_SYMBOL_STUBS ||
type == S_MOD_INIT_FUNC_POINTERS ||
type == S_MOD_TERM_FUNC_POINTERS)
as_fatal("incompatible feature used: section type %s (must "
"specify \"-dynamic\" to be "
"used)", type_name->name);
}
frcP = section_new(segname, sectname, type, attribute, sizeof_stub);
*p = c;
*q = d;
demand_empty_rest_of_line();
}
static
void
s_zerofill(
uintptr_t value)
{
char *directive, *segname, *sectname, c, d, *p, *q, *name;
section_t s;
frchainS *frcP;
symbolS *symbolP;
uint64_t size;
int align;
if(value == S_THREAD_LOCAL_ZEROFILL){
directive = "tbss";
frcP = section_new("__DATA", "__thread_bss", value, 0, 0);
if(frcP->frch_root == NULL){
frcP->frch_root = xmalloc(SIZEOF_STRUCT_FRAG);
frcP->frch_last = frcP->frch_root;
memset(frcP->frch_root, '\0', SIZEOF_STRUCT_FRAG);
}
}
else{
directive = "zerofill";
segname = input_line_pointer;
do{
c = *input_line_pointer++ ;
}while(c != ' ' && c != ',' && c != '\0' && c != '\n');
p = input_line_pointer - 1;
while(c == ' '){
c = *input_line_pointer++ ;
}
if(c != ','){
as_bad("Expected comma after segment-name");
ignore_rest_of_line();
return;
}
SKIP_WHITESPACE();
sectname = input_line_pointer;
do{
d = *input_line_pointer++ ;
}while(d != ',' && d != '\0' && d != '\n');
if(p + 1 == input_line_pointer){
as_bad("Expected section-name after comma");
ignore_rest_of_line();
return;
}
q = input_line_pointer - 1;
*p = 0;
if(strlen(segname) > sizeof(s.segname)){
as_bad("segment-name: %s too long (maximum %ld characters)",
segname, sizeof(s.segname));
ignore_rest_of_line();
*p = c;
return;
}
*q = 0;
if(strlen(sectname) > sizeof(s.sectname)){
as_bad("section-name: %s too long (maximum %ld characters)",
sectname, sizeof(s.sectname));
ignore_rest_of_line();
*p = c;
*q = d;
return;
}
frcP = section_new(segname, sectname, value, 0, 0);
if(frcP->frch_root == NULL){
frcP->frch_root = xmalloc(SIZEOF_STRUCT_FRAG);
frcP->frch_last = frcP->frch_root;
memset(frcP->frch_root, '\0', SIZEOF_STRUCT_FRAG);
}
*p = c;
*q = d;
if(d != ',')
return;
}
if(*input_line_pointer == '"')
name = input_line_pointer + 1;
else
name = input_line_pointer;
c = get_symbol_end();
p = input_line_pointer;
*p = c;
SKIP_WHITESPACE();
if(*input_line_pointer != ','){
as_bad("Expected comma after symbol-name");
ignore_rest_of_line();
return;
}
input_line_pointer ++;
if((int)(size = get_absolute_expression()) < 0){
as_bad("%s size (%lld.) <0! Ignored.", directive, size);
ignore_rest_of_line();
return;
}
align = 0;
if(*input_line_pointer == ','){
input_line_pointer++;
align = get_absolute_expression();
if(align > MAX_ALIGNMENT){
as_warn("Alignment too large: %d. assumed.", MAX_ALIGNMENT);
align = MAX_ALIGNMENT;
}
else if(align < 0){
as_warn("Alignment negative. 0 assumed.");
align = 0;
}
if(frcP->frch_section.align < (uint32_t)align)
frcP->frch_section.align = align;
}
*p = 0;
symbolP = symbol_find_or_make(name);
*p = c;
if((symbolP->sy_type & N_TYPE) == N_UNDF && symbolP->sy_value == 0){
frcP->frch_root->fr_address = rnd(frcP->frch_root->fr_address,
1 << align);
symbolP->sy_value = frcP->frch_root->fr_address;
symbolP->sy_type = N_SECT | (symbolP->sy_type & (N_EXT | N_PEXT));
symbolP->sy_other = frcP->frch_nsect;
symbolP->sy_frag = frcP->frch_root;
frcP->frch_root->fr_address += size;
}
else
as_bad("Ignoring attempt to re-define symbol.");
demand_empty_rest_of_line();
}
static
void
s_reference(
uintptr_t value)
{
char *name;
char c;
char *p;
symbolS *symbolP;
if(* input_line_pointer == '"')
name = input_line_pointer + 1;
else
name = input_line_pointer;
c = get_symbol_end();
p = input_line_pointer;
*p = 0;
symbolP = symbol_find_or_make(name);
symbolP->sy_desc |= N_NO_DEAD_STRIP;
*p = c;
demand_empty_rest_of_line();
}
static
void
s_lazy_reference(
uintptr_t value)
{
char *name;
char c;
char *p;
symbolS *symbolP;
if(!flagseen['k'])
as_fatal("incompatible feature used: .lazy_reference (must specify "
"\"-dynamic\" to be used)");
if(* input_line_pointer == '"')
name = input_line_pointer + 1;
else
name = input_line_pointer;
c = get_symbol_end();
p = input_line_pointer;
*p = 0;
symbolP = symbol_find_or_make(name);
if((symbolP->sy_type & N_TYPE) == N_UNDF && symbolP->sy_value == 0)
symbolP->sy_desc |= REFERENCE_FLAG_UNDEFINED_LAZY;
symbolP->sy_desc |= N_NO_DEAD_STRIP;
*p = c;
demand_empty_rest_of_line();
}
static
void
s_weak_reference(
uintptr_t value)
{
char *name;
char c;
char *p;
symbolS *symbolP;
if(!flagseen['k'])
as_fatal("incompatible feature used: .weak_reference (must specify "
"\"-dynamic\" to be used)");
if(* input_line_pointer == '"')
name = input_line_pointer + 1;
else
name = input_line_pointer;
c = get_symbol_end();
p = input_line_pointer;
*p = 0;
symbolP = symbol_find_or_make(name);
if((symbolP->sy_type & N_TYPE) == N_UNDF && symbolP->sy_value == 0)
symbolP->sy_desc |= N_WEAK_REF;
*p = c;
demand_empty_rest_of_line();
}
static
void
s_weak_definition(
uintptr_t value)
{
char *name;
char c;
char *p;
symbolS *symbolP;
if(* input_line_pointer == '"')
name = input_line_pointer + 1;
else
name = input_line_pointer;
c = get_symbol_end();
p = input_line_pointer;
*p = 0;
symbolP = symbol_find_or_make(name);
symbolP->sy_desc |= N_WEAK_DEF;
*p = c;
demand_empty_rest_of_line();
}
static
void
s_weak_def_can_be_hidden(
uintptr_t value)
{
char *name;
char c;
char *p;
symbolS *symbolP;
if(* input_line_pointer == '"')
name = input_line_pointer + 1;
else
name = input_line_pointer;
c = get_symbol_end();
p = input_line_pointer;
*p = 0;
symbolP = symbol_find_or_make(name);
symbolP->sy_desc |= (N_WEAK_DEF | N_WEAK_REF);
*p = c;
demand_empty_rest_of_line();
}
static
void
s_no_dead_strip(
uintptr_t value)
{
char *name;
char c;
char *p;
symbolS *symbolP;
if(* input_line_pointer == '"')
name = input_line_pointer + 1;
else
name = input_line_pointer;
c = get_symbol_end();
p = input_line_pointer;
*p = 0;
symbolP = symbol_find_or_make(name);
symbolP->sy_desc |= N_NO_DEAD_STRIP;
*p = c;
demand_empty_rest_of_line();
}
static
void
s_symbol_resolver(
uintptr_t value)
{
char *name;
char c;
char *p;
symbolS *symbolP;
if(* input_line_pointer == '"')
name = input_line_pointer + 1;
else
name = input_line_pointer;
c = get_symbol_end();
p = input_line_pointer;
*p = 0;
symbolP = symbol_find_or_make(name);
symbolP->sy_desc |= N_SYMBOL_RESOLVER;
*p = c;
demand_empty_rest_of_line();
}
static
void
s_include(
uintptr_t value)
{
char *filename;
int length;
symbolS *symbolP;
if((filename = demand_copy_string( & length ) )) {
demand_empty_rest_of_line();
read_an_include_file(filename);
}
if(flagseen['g'] && frchain_now->frch_nsect == text_nsect){
symbolP = symbol_new(
physical_input_file,
132 ,
text_nsect,
0,
obstack_next_free(&frags) - frag_now->fr_literal,
frag_now);
}
}
void
demand_empty_rest_of_line(
void)
{
SKIP_WHITESPACE();
if(is_end_of_line(*input_line_pointer))
input_line_pointer++;
else
ignore_rest_of_line();
}
void
s_ignore(
uintptr_t arg ATTRIBUTE_UNUSED)
{
totally_ignore_line ();
}
void
ignore_rest_of_line(
void)
{
if(!is_end_of_line(*input_line_pointer)){
as_bad("Rest of line ignored. 1st junk character valued %d (%c).",
*input_line_pointer, *input_line_pointer);
while(input_line_pointer < buffer_limit &&
!is_end_of_line(*input_line_pointer))
input_line_pointer++;
}
input_line_pointer++;
know(is_end_of_line(input_line_pointer[-1]));
}
static
void
stab(
uintptr_t what)
{
symbolS *symbolP;
char *string;
int saved_type;
int length;
int goof;
int32_t longint;
saved_type = 0;
symbolP = NULL;
goof = FALSE;
if(what == 's'){
string = demand_copy_C_string(&length);
SKIP_WHITESPACE();
if(*input_line_pointer == ',')
input_line_pointer ++;
else{
as_bad("I need a comma after symbol's name");
goof = TRUE;
}
}
else
string = "";
if(!goof){
symbolP = symbol_new(string, 0,0,0,0,(struct frag *)0);
switch(what){
case 'd':
symbolP->sy_name = NULL;
symbolP->sy_value = obstack_next_free(&frags) -
frag_now->fr_literal;
symbolP->sy_frag = frag_now;
break;
case 'n':
case 's':
symbolP->sy_frag = &zero_address_frag;
break;
default:
BAD_CASE( (int)what );
break;
}
if(get_absolute_expression_and_terminator(&longint) == ','){
saved_type = longint;
symbolP->sy_type = longint;
}
else{
as_bad("I want a comma after the n_type expression");
goof = TRUE;
input_line_pointer--;
}
}
if(!goof){
if(get_absolute_expression_and_terminator(&longint) == ',')
symbolP->sy_other = longint;
else {
as_bad("I want a comma after the n_other expression");
goof = TRUE;
input_line_pointer--;
}
}
if(!goof){
symbolP->sy_desc = get_absolute_expression();
if(what == 's' || what == 'n'){
if(*input_line_pointer != ','){
as_bad( "I want a comma after the n_desc expression" );
goof = TRUE;
}
else
input_line_pointer ++;
}
}
if((!goof) && (what=='s' || what=='n')){
pseudo_set(symbolP);
symbolP->sy_type = saved_type;
}
else if(!goof){
symbolP->sy_other = frchain_now->frch_nsect;
}
if(goof)
ignore_rest_of_line();
else
demand_empty_rest_of_line();
}
void
pseudo_set(
symbolS *symbolP)
{
expressionS exp;
segT segment;
int ext;
know(symbolP);
ext = (symbolP->sy_type & (N_EXT | N_PEXT));
segment = expression(&exp);
switch(segment){
case SEG_BIG:
as_bad("%s number illegal. Absolute 0 assumed.",
exp.X_add_number > 0 ? "Bignum" : "Floating-Point");
symbolP->sy_type = N_ABS | ext;
symbolP->sy_other = 0;
symbolP->sy_value = 0;
symbolP->sy_frag = &zero_address_frag;
break;
case SEG_NONE:
as_bad("No expression: Using absolute 0");
symbolP->sy_type = N_ABS | ext;
symbolP->sy_other = 0;
symbolP->sy_value = 0;
symbolP->sy_frag = &zero_address_frag;
break;
case SEG_DIFFSECT:
if(exp.X_add_symbol && exp.X_subtract_symbol){
if(exp.X_add_symbol->sy_frag !=
exp.X_subtract_symbol->sy_frag ||
exp.X_add_symbol->sy_type == N_UNDF ||
exp.X_subtract_symbol->sy_type == N_UNDF ){
expressionS *expression;
expression = xmalloc(sizeof(expressionS));
*expression = exp;
symbolP->expression = expression;
}
else{
exp.X_add_number += exp.X_add_symbol->sy_value -
exp.X_subtract_symbol->sy_value;
}
}
else if(exp.X_add_symbol &&
exp.X_subtract_symbol == NULL &&
exp.X_add_symbol->expression != NULL){
expressionS *expression;
expression = xmalloc(sizeof(expressionS));
memcpy(expression, exp.X_add_symbol->expression,
sizeof(expressionS));
symbolP->expression = expression;
}
else
as_bad("Complex expression. Absolute segment assumed." );
symbolP->sy_type = N_ABS | ext;
symbolP->sy_other = 0;
symbolP->sy_value = exp.X_add_number;
symbolP->sy_frag = &zero_address_frag;
break;
case SEG_ABSOLUTE:
symbolP->sy_type = N_ABS | ext;
symbolP->sy_other = 0;
symbolP->sy_value = exp.X_add_number;
symbolP->sy_frag = &zero_address_frag;
symbolP->expression = NULL;
break;
case SEG_SECT:
symbolP->sy_type = N_SECT | ext;
symbolP->sy_other = exp.X_add_symbol->sy_other;
symbolP->sy_value = exp.X_add_number + exp.X_add_symbol->sy_value;
symbolP->sy_frag = exp.X_add_symbol->sy_frag;
break;
case SEG_UNKNOWN:
symbolP->sy_forward = exp.X_add_symbol;
break;
default:
BAD_CASE(segment);
break;
}
}
void
cons(
uintptr_t nbytes)
{
char c;
signed_expr_t
mask,
unmask,
get,
use;
char *p;
segT segment;
expressionS exp;
#ifndef TC_CONS_FIX_NEW
fixS *fixP;
#endif
memset(&exp, '\0', sizeof(exp));
if(nbytes >= (int)sizeof(signed_expr_t))
mask = 0;
else
mask = ~0ULL << (BITS_PER_CHAR * nbytes);
unmask = ~mask;
if(is_it_end_of_statement()){
c = 0;
input_line_pointer++;
}
else
c = ',';
while(c == ','){
#ifdef TC_PARSE_CONS_EXPRESSION
segment = TC_PARSE_CONS_EXPRESSION(&exp, nbytes);
#else
segment = expression(&exp);
#endif
if(segment == SEG_DIFFSECT && exp.X_add_symbol == NULL){
as_bad("Subtracting symbol \"%s\"(segment\"%s\") is too "
"hard. Absolute segment assumed.",
exp.X_subtract_symbol->sy_name,
seg_name[(int)N_TYPE_seg[
exp.X_subtract_symbol->sy_type & N_TYPE]]);
segment = SEG_ABSOLUTE;
}
p = frag_more(nbytes);
switch(segment){
case SEG_BIG:
if(exp.X_add_number > 0 &&
(((LITTLENUM_NUMBER_OF_BITS * exp.X_add_number) / 8) <=
sizeof(int64_t))){
int i;
int64_t sum;
sum = 0;
for(i = 0; i < exp.X_add_number; ++i)
sum = (sum << LITTLENUM_NUMBER_OF_BITS) +
generic_bignum[(exp.X_add_number - 1) - i];
md_number_to_chars(p, sum, nbytes);
}
else
{
as_bad("%s number illegal. Absolute 0 assumed.",
exp.X_add_number > 0 ? "Bignum" : "Floating-Point");
md_number_to_chars(p, (int32_t)0, nbytes);
}
break;
case SEG_NONE:
as_bad("0 assumed for missing expression");
exp.X_add_number = 0;
know(exp.X_add_symbol == NULL);
case SEG_ABSOLUTE:
get = exp.X_add_number;
use = get & unmask;
if((get & mask) && (get & mask) != mask){
as_bad("Value 0x%llx truncated to 0x%llx.", get, use);
}
dwarf2_emit_insn(nbytes);
md_number_to_chars(p, use, nbytes);
break;
case SEG_DIFFSECT:
case SEG_UNKNOWN:
case SEG_SECT:
#ifdef TC_CONS_FIX_NEW
TC_CONS_FIX_NEW(frag_now,
p - frag_now->fr_literal,
nbytes,
&exp);
#else
fixP = fix_new(frag_now,
p - frag_now->fr_literal,
nbytes,
exp.X_add_symbol,
exp.X_subtract_symbol,
exp.X_add_number,
0,
0,
0);
fixP->fx_sectdiff_divide_by_two = exp.X_sectdiff_divide_by_two;
#endif
break;
default:
BAD_CASE(segment);
break;
}
c = *input_line_pointer++;
}
input_line_pointer--;
demand_empty_rest_of_line();
}
#ifdef M68K
void
big_cons(
uintptr_t nbytes)
{
char c;
int radix;
int32_t length;
int digit;
int carry;
int work;
char *p,*q;
int i;
if(is_it_end_of_statement()){
c = 0;
}
else{
c = ',';
--input_line_pointer;
}
while(c == ','){
++input_line_pointer;
SKIP_WHITESPACE();
c = *input_line_pointer;
if(c == '0'){
c = *++input_line_pointer;
if(c == 'x' || c=='X'){
c = *++input_line_pointer;
radix = 16;
}
else{
radix = 8;
}
}
else{
radix = 10;
}
if(hex_value[(int)c] >= radix){
as_bad("Missing digits. 0 assumed.");
}
bignum_high = bignum_low - 1;
for( ;
(digit = hex_value[(int)c]) < radix;
c = *++input_line_pointer){
carry = digit;
for(p = bignum_low; p <= bignum_high; p++){
work = (*p & MASK_CHAR) * radix + carry;
*p = work & MASK_CHAR;
carry = work >> BITS_PER_CHAR;
}
if(carry){
grow_bignum();
*bignum_high = carry & MASK_CHAR;
know((carry & ~ MASK_CHAR) == 0);
}
}
length = bignum_high - bignum_low + 1;
if(length > nbytes){
as_bad("Most significant bits truncated in integer constant.");
}
else{
int32_t leading_zeroes;
for(leading_zeroes = nbytes - length;
leading_zeroes;
leading_zeroes--){
grow_bignum();
*bignum_high = 0;
}
}
p = frag_more(nbytes);
if(md_target_byte_sex == BIG_ENDIAN_BYTE_SEX){
q = (char *)bignum_low;
for(i = nbytes - 1; i >= 0; i--)
*p++ = q[i];
}
else{
memcpy(p, bignum_low, (int)nbytes);
}
SKIP_WHITESPACE();
c = *input_line_pointer;
}
demand_empty_rest_of_line();
}
static
void
grow_bignum(
void)
{
int32_t length;
bignum_high++;
if(bignum_high >= bignum_limit)
{
length = bignum_limit - bignum_low;
bignum_low = xrealloc(bignum_low, length + length);
bignum_high = bignum_low + length;
bignum_limit = bignum_low + length + length;
}
}
#endif
void
float_cons(
uintptr_t float_type)
{
char *p;
char c;
int length;
char *err;
char temp[MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT];
if(is_it_end_of_statement()){
c = 0;
++input_line_pointer;
}
else{
c = ',';
}
while(c == ','){
SKIP_WHITESPACE();
if(input_line_pointer[0] == '0' && isalpha(input_line_pointer[1]))
input_line_pointer+=2;
err = md_atof(float_type, temp, &length);
know(length <= MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT);
know(length > 0);
if(err != NULL && *err != '\0'){
as_bad( "Bad floating literal: %s", err);
ignore_rest_of_line();
c = 0;
}
else{
p = frag_more(length);
memcpy(p, temp, length);
SKIP_WHITESPACE();
c = *input_line_pointer ++;
}
}
--input_line_pointer;
demand_empty_rest_of_line();
}
static void
emit_leb128_expr (expressionS *exp, int sign)
{
segT op = exp->X_op;
#ifdef notyet
unsigned int nbytes;
#endif
if (op == O_absent)
{
as_warn (_("zero assumed for missing expression"));
exp->X_add_number = 0;
op = O_constant;
}
else if (op == O_big && exp->X_add_number <= 0)
{
as_bad (_("floating point number invalid"));
exp->X_add_number = 0;
op = O_constant;
}
#ifdef notyet
else if (op == O_register)
{
as_warn (_("register value used as expression"));
op = O_constant;
}
else if (op == O_constant
&& sign
&& (exp->X_add_number < 0) != !exp->X_unsigned)
{
convert_to_bignum (exp);
op = O_big;
}
nbytes = (unsigned int) -1;
if (check_eh_frame (exp, &nbytes))
abort ();
#ifdef md_cons_align
md_cons_align (1);
#endif
#endif
if (op == O_constant)
{
valueT value = exp->X_add_number;
int size;
char *p;
size = sizeof_leb128 (value, sign);
p = frag_more (size);
output_leb128 (p, value, sign);
}
#ifdef notyet
else if (op == O_big)
{
int size;
char *p;
size = output_big_leb128 (NULL, generic_bignum, exp->X_add_number, sign);
p = frag_more (size);
output_big_leb128 (p, generic_bignum, exp->X_add_number, sign);
}
#endif
else
{
#ifdef OLD
frag_var (rs_leb128, sizeof_uleb128 (~(valueT) 0), 0, sign,
make_expr_symbol (exp), 0, (char *) NULL);
#else
symbolS *sym;
expressionS *expression;
sym = symbol_temp_new(exp->X_add_symbol->sy_other , 0, NULL);
expression = xmalloc(sizeof(expressionS));
*expression = *exp;
sym->expression = expression;
sym->sy_frag = &zero_address_frag;
frag_var (rs_leb128, sizeof_leb128 ( ((valueT) (~(valueT) 0) >> 1), 0), 0, sign,
sym, 0, (char *) NULL);
frchain_now->has_rs_leb128s = TRUE;
#endif
}
}
static
void
s_leb128(
uintptr_t sign)
{
expressionS exp;
#ifdef md_flush_pending_output
md_flush_pending_output ();
#endif
do
{
expression (&exp);
emit_leb128_expr (&exp, sign);
}
while (*input_line_pointer++ == ',');
input_line_pointer--;
demand_empty_rest_of_line ();
}
void
stringer(
uintptr_t append_zero)
{
int c;
if(is_it_end_of_statement()){
c = 0;
++ input_line_pointer;
}
else{
c = ',';
}
for( ; c == ','; c = *input_line_pointer++){
SKIP_WHITESPACE();
if(*input_line_pointer == '\"'){
++input_line_pointer;
while((c = next_char_of_string()) >= 0){
FRAG_APPEND_1_CHAR(c);
}
if(append_zero){
FRAG_APPEND_1_CHAR(0);
}
know(input_line_pointer[-1] == '\"');
}
else{
as_bad("Expected \"-ed string");
}
SKIP_WHITESPACE();
}
--input_line_pointer;
demand_empty_rest_of_line();
}
static
int
next_char_of_string(
void)
{
int c;
int32_t number, i;
c = *input_line_pointer++;
c = (c & MASK_CHAR);
switch(c){
case '\"':
#ifdef PPC
if(flagseen[(int)'p'] == TRUE)
break;
#endif
c = -1;
break;
#ifdef PPC
case '\'':
if(flagseen[(int)'p'] == TRUE)
c = -1;
break;
#endif
case '\\':
c = *input_line_pointer++;
switch(c){
case 'b':
c = '\b';
break;
case 'f':
c = '\f';
break;
case 'n':
c = '\n';
break;
case 'r':
c = '\r';
break;
case 't':
c = '\t';
break;
case '\\':
case '"':
case '\'':
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
for(i = 0, number = 0;
i < 3 && isdigit(c) && c < '8';
i++, c = *input_line_pointer++)
number = number * 8 + c - '0';
c = number;
--input_line_pointer;
break;
case '\n':
c = '\n';
break;
default:
as_bad( "Bad escaped character in string, '?' assumed" );
c = '?';
break;
}
break;
default:
break;
}
return(c);
}
static
segT
get_segmented_expression(
expressionS *expP)
{
segT retval;
retval = expression(expP);
if(retval == SEG_NONE || retval == SEG_BIG){
as_bad("Expected address expression: absolute 0 assumed");
retval = expP->X_seg = SEG_ABSOLUTE;
expP->X_add_number = 0;
expP->X_add_symbol = NULL;
expP->X_subtract_symbol = NULL;
}
return(retval);
}
segT
get_known_segmented_expression(
expressionS *expP)
{
segT retval;
char *name1;
char *name2;
retval = get_segmented_expression(expP);
if(retval == SEG_UNKNOWN){
name1 = expP->X_add_symbol ?
expP->X_add_symbol->sy_name : "";
name2 = expP->X_subtract_symbol ?
expP->X_subtract_symbol->sy_name : "";
if(name1 && name2){
as_bad("Symbols \"%s\" \"%s\" are undefined: absolute 0 "
"assumed.", name1, name2);
}
else{
as_bad("Symbol \"%s\" undefined: absolute 0 assumed.",
name1 ? name1 : name2);
}
retval = SEG_ABSOLUTE;
expP->X_seg = SEG_ABSOLUTE;
expP->X_add_number = 0;
expP->X_add_symbol = NULL;
expP->X_subtract_symbol = NULL;
}
know(retval == SEG_ABSOLUTE ||
retval == SEG_SECT ||
retval == SEG_DIFFSECT);
return(retval);
}
signed_target_addr_t
get_absolute_expression(
void)
{
expressionS exp;
segT s;
s = expression(&exp);
if(s != SEG_ABSOLUTE){
if(s != SEG_NONE){
as_bad("Bad Absolute Expression, absolute 0 assumed.");
}
exp.X_add_number = 0;
}
return(exp.X_add_number);
}
static
char
get_absolute_expression_and_terminator(
int32_t *val_pointer)
{
*val_pointer = get_absolute_expression();
return(*input_line_pointer++);
}
char *
demand_copy_C_string(
int *len_pointer)
{
char *s;
int len;
if((s = demand_copy_string(len_pointer))){
for(len = *len_pointer; len > 0; len--){
if(*s == '\0'){
s = 0;
len = 1;
*len_pointer = 0;
as_bad("This string may not contain \'\\0\'");
}
}
}
return(s);
}
static
char *
demand_copy_string(
int *lenP)
{
int c;
int len;
char *retval;
len = 0;
SKIP_WHITESPACE();
#ifdef PPC
if((flagseen[(int)'p'] == TRUE && *input_line_pointer == '\'') ||
(flagseen[(int)'p'] == FALSE && *input_line_pointer == '\"'))
#else
if(*input_line_pointer == '\"')
#endif
{
input_line_pointer++;
while((c = next_char_of_string()) >= 0){
(void)(obstack_1grow(¬es, c));
len++;
}
(void)(obstack_1grow(¬es, '\0'));
retval = obstack_finish(¬es);
}
else{
as_bad("Missing string");
retval = NULL;
ignore_rest_of_line();
}
*lenP = len;
return(retval);
}
static
int
is_it_end_of_statement(
void)
{
SKIP_WHITESPACE();
return(is_end_of_line(*input_line_pointer));
}
static
void
equals(
char *sym_name)
{
struct symbol *symbolP;
segT segment;
expressionS exp;
char *p;
if(sym_name[0]=='.' && sym_name[1]=='\0'){
if(input_line_pointer[1] == '=')
input_line_pointer += 2;
else
*input_line_pointer++ = '=';
if(*input_line_pointer==' ' || *input_line_pointer=='\t')
input_line_pointer++;
segment = get_known_segmented_expression(&exp);
if((segment != SEG_SECT ||
exp.X_add_symbol->sy_other != frchain_now->frch_nsect) &&
segment != SEG_ABSOLUTE)
as_bad("Illegal expression. current section assumed.");
p = frag_var(rs_org,
1,
1,
(relax_substateT)0,
exp.X_add_symbol,
exp.X_add_number,
(char *)0);
*p = 0;
return;
}
symbolP = symbol_find_or_make(sym_name);
if(symbolP->sy_type & N_ABS)
symbolP->sy_desc |= N_NO_DEAD_STRIP;
if(input_line_pointer[1] == '=')
input_line_pointer += 2;
else
*input_line_pointer++ = '=';
if(*input_line_pointer==' ' || *input_line_pointer=='\t')
input_line_pointer++;
pseudo_set(symbolP);
}
static
void
s_if(
uintptr_t value)
{
if(if_depth >= MAX_IF_DEPTH)
as_fatal("You can't nest if's more than %d levels deep",
MAX_IF_DEPTH);
last_states[if_depth++] = the_cond_state;
the_cond_state.the_cond = if_cond;
if(the_cond_state.ignore)
totally_ignore_line();
else{
the_cond_state.cond_met = get_absolute_expression();
the_cond_state.ignore = !the_cond_state.cond_met;
demand_empty_rest_of_line();
}
}
static
void
s_elseif(
uintptr_t value)
{
int last_ignore_state;
if(the_cond_state.the_cond != if_cond &&
the_cond_state.the_cond != elseif_cond)
as_fatal("Encountered a .elseif that doesn't follow a .if or an "
".elseif");
the_cond_state.the_cond = elseif_cond;
last_ignore_state = FALSE;
if(if_depth)
last_ignore_state = last_states[if_depth-1].ignore;
if(last_ignore_state || the_cond_state.cond_met){
the_cond_state.ignore = TRUE;
totally_ignore_line();
}
else{
the_cond_state.cond_met = get_absolute_expression();
the_cond_state.ignore = !the_cond_state.cond_met;
demand_empty_rest_of_line();
}
}
static
void
s_else(
uintptr_t value)
{
int last_ignore_state;
if(the_cond_state.the_cond != if_cond &&
the_cond_state.the_cond != elseif_cond)
as_fatal("Encountered a .else that doesn't follow a .if or an "
".elseif");
the_cond_state.the_cond = else_cond;
last_ignore_state = FALSE;
if(if_depth)
last_ignore_state = last_states[if_depth-1].ignore;
if(last_ignore_state || the_cond_state.cond_met)
the_cond_state.ignore = TRUE;
else
the_cond_state.ignore = FALSE;
demand_empty_rest_of_line();
}
static
void
s_endif(
uintptr_t value)
{
if((the_cond_state.the_cond == no_cond) || (if_depth == 0))
as_fatal("Encountered a .endif that doesn't follow a .if or .else");
the_cond_state = last_states[--if_depth];
demand_empty_rest_of_line();
}
void
totally_ignore_line(
void)
{
if(!is_end_of_line(*input_line_pointer)){
while(input_line_pointer < buffer_limit &&
!is_end_of_line(*input_line_pointer)){
input_line_pointer ++;
}
}
input_line_pointer++;
know(is_end_of_line(input_line_pointer[-1]));
}
static
void
s_macros_on(
uintptr_t value)
{
macros_on = TRUE;
demand_empty_rest_of_line();
}
void
s_macros_off(
uintptr_t value)
{
macros_on = FALSE;
demand_empty_rest_of_line();
}
void
s_macro(
uintptr_t value)
{
int c;
pseudo_typeS *pop;
if(macro_name)
as_bad("Can't define a macro inside another macro definition");
else{
SKIP_WHITESPACE();
while(is_part_of_name(c = *input_line_pointer ++))
(void)(obstack_1grow (¯os, c));
(void)(obstack_1grow(¯os, '\0'));
--input_line_pointer;
macro_name = obstack_finish(¯os);
if(macro_name == NULL)
as_bad("Missing name of macro");
if(*macro_name == '.'){
pop = (pseudo_typeS *)hash_find(po_hash, macro_name + 1);
if(pop != NULL)
as_bad("Pseudo-op name: %s can't be a macro name",
macro_name);
}
}
totally_ignore_line();
}
void
s_endmacro(
uintptr_t value)
{
const char *errorString;
if(!macro_name){
as_bad ("This .endmacro does not match with a preceding .macro");
ignore_rest_of_line();
}
else{
(void)(obstack_1grow(¯os, '\0'));
errorString = hash_insert(ma_hash, macro_name,
obstack_finish(¯os));
if(errorString != NULL && *errorString)
as_warn("The macro named \"%s\" is already defined",
macro_name);
macro_name = NULL;
}
}
static
void
macro_begin(
void)
{
ma_hash = hash_new();
obstack_begin(¯os, 5000);
}
void
add_to_macro_definition(
char *char_pointer)
{
char c;
do{
c = *char_pointer ++;
know(c != '\0');
(void)(obstack_1grow(¯os, c));
}while((c != ':') && !(is_end_of_line(c)));
if(char_pointer > input_line_pointer)
input_line_pointer = char_pointer;
}
static
void
expand_macro(
char *macro_contents)
{
char *buffer;
char c;
int index, nargs;
char *last_buffer_limit;
int last_count_lines;
char *last_input_line_pointer;
char *arguments [10];
if(macro_depth >= MAX_MACRO_DEPTH)
as_fatal("You can't nest macros more than %d levels deep",
MAX_MACRO_DEPTH);
macro_depth++;
nargs = 0;
for(index = 0; index < 10; index ++){
if(*input_line_pointer == ' ')
++input_line_pointer;
know(*input_line_pointer != ' ');
c = *input_line_pointer;
if(is_end_of_line(c))
arguments[index] = NULL;
else{
int parenthesis_depth = 0;
do{
SKIP_WHITESPACE();
c = *input_line_pointer++;
if(parenthesis_depth){
if(c == ')')
parenthesis_depth --;
}
else{
if(c == '(')
parenthesis_depth ++;
else
if(is_end_of_line(c) ||
(c == ' ') || (c == ','))
break;
}
know(c != '\0');
if(is_end_of_line(c))
as_bad("mismatched parenthesis");
(void)(obstack_1grow(¯os, c));
}while(1);
(void)(obstack_1grow(¯os, '\0'));
arguments[index] = obstack_finish(¯os);
nargs++;
if(is_end_of_line(c))
--input_line_pointer;
else if(c == ' ')
if(*input_line_pointer == ',')
input_line_pointer++;
}
}
if(!is_end_of_line(c)){
as_bad("More than 10 arguments not allowed for macros");
ignore_rest_of_line();
}
(void)(obstack_1grow(¯os, '\n'));
while((c = *macro_contents++)){
if(c == '$'){
if(*macro_contents == '$'){
macro_contents++;
}
else if((*macro_contents >= '0') && (*macro_contents <= '9')){
index = *macro_contents++ - '0';
last_input_line_pointer = macro_contents;
macro_contents = arguments[index];
if(macro_contents){
while ((c = * macro_contents ++))
(void)(obstack_1grow (¯os, c));
}
macro_contents = last_input_line_pointer;
continue;
}
else if (*macro_contents == 'n'){
macro_contents++ ;
(void)(obstack_1grow(¯os, nargs + '0'));
continue;
}
}
(void)(obstack_1grow (¯os, c));
}
(void)(obstack_1grow (¯os, '\n'));
(void)(obstack_1grow (¯os, '\0'));
last_buffer_limit = buffer_limit;
last_count_lines = count_lines;
last_input_line_pointer = input_line_pointer;
buffer_limit = obstack_next_free (¯os) - 1;
buffer = obstack_finish (¯os);
count_lines = FALSE;
#ifdef PPC
if(flagseen[(int)'p'] == TRUE)
ppcasm_parse_a_buffer(buffer + 1);
else
#endif
parse_a_buffer(buffer + 1);
obstack_free (¯os, buffer);
for(index = 9; index >= 0; index --)
if(arguments[index])
obstack_free(¯os, arguments[index]);
buffer_limit = last_buffer_limit;
count_lines = last_count_lines;
input_line_pointer = last_input_line_pointer;
macro_depth--;
}
static
void
s_dump(
uintptr_t value)
{
char *filename;
int length;
static char null_string[] = "";
if((filename = demand_copy_string(&length))){
demand_empty_rest_of_line();
if((dump_fp = fopen(filename, "w+"))){
hash_traverse(ma_hash, write_macro);
fwrite(null_string, 1, 1, dump_fp);
hash_traverse(sy_hash, write_symbol);
fwrite(null_string, 1, 1, dump_fp);
fclose(dump_fp);
}
else
as_bad("couldn't write to dump file: \"%s\"", filename);
}
}
static
void
write_macro(
const char *string,
PTR value1)
{
char *value = value1;
know(string);
know(value);
know(strlen(string));
fwrite(string, (strlen(string) + 1), 1, dump_fp);
fwrite(value, (strlen(value) + 1), 1, dump_fp);
}
static
void
write_symbol(
const char *string,
PTR value)
{
symbolS *symbolP;
symbolP = (symbolS *)value;
know(symbolP);
if(((symbolP->sy_type) & N_TYPE) == N_ABS){
know(string);
know(strlen(string));
fwrite(string, (strlen(string) + 1), 1, dump_fp);
fwrite(&(symbolP -> sy_value), 4, 1, dump_fp);
}
}
static
void
s_load(
uintptr_t value)
{
char *char_pointer;
char *filename;
int length;
char the_char;
symbolS *the_symbol;
symbolS *temp_symbol_lastP;
static symbolS *dump_symbol_lastP;
if((filename = demand_copy_string(&length))){
demand_empty_rest_of_line();
if((dump_fp = fopen(filename, "r+"))){
do{
do{
the_char = getc_unlocked(dump_fp);
(void)(obstack_1grow(¯os, the_char));
}while(the_char);
char_pointer = obstack_finish (¯os);
if(!(*char_pointer))
break;
do{
the_char = getc_unlocked(dump_fp);
(void)(obstack_1grow(¯os, the_char));
}while(the_char);
if(hash_insert(ma_hash, char_pointer,
obstack_finish(¯os)))
as_bad("a macro named \"%s\" encountered in a .load "
"is already defined", char_pointer);
}while(1);
temp_symbol_lastP = symbol_lastP;
symbol_lastP = dump_symbol_lastP;
do{
do{
the_char = getc_unlocked(dump_fp);
(void)(obstack_1grow(¯os, the_char));
}while(the_char);
char_pointer = obstack_base(¯os);
obstack_next_free(¯os) = char_pointer;
if(!(*char_pointer))
break;
the_symbol = symbol_find_or_make(char_pointer);
the_symbol->sy_type = N_ABS;
char_pointer = (char *)&the_symbol->sy_value;
*char_pointer++ = getc_unlocked(dump_fp);
*char_pointer++ = getc_unlocked(dump_fp);
*char_pointer++ = getc_unlocked(dump_fp);
*char_pointer++ = getc_unlocked(dump_fp);
the_symbol->sy_frag = &zero_address_frag;
}while(1);
dump_symbol_lastP = symbol_lastP;
symbol_lastP = temp_symbol_lastP;
fclose(dump_fp);
}
else
as_fatal("Couldn't find the dump file: \"%s\"", filename);
}
}
static
void
s_subsections_via_symbols(
uintptr_t value)
{
demand_empty_rest_of_line();
subsections_via_symbols = TRUE;
}
static
void
s_machine(
uintptr_t value)
{
char *arch_name, c;
struct arch_flag arch_flag;
cpu_subtype_t new_cpusubtype;
const struct arch_flag *family_arch_flag;
arch_name = input_line_pointer;
do{
c = *input_line_pointer++ ;
}while(c != '\0' && c != '\n' && c != '\t' && c != ' ');
*--input_line_pointer = 0;
if(force_cpusubtype_ALL == FALSE){
family_arch_flag = NULL;
if(strcmp(arch_name, "all") == 0){
family_arch_flag = get_arch_family_from_cputype(md_cputype);
if(family_arch_flag != NULL)
arch_flag = *family_arch_flag;
}
if(family_arch_flag == NULL &&
get_arch_from_flag(arch_name, &arch_flag) == 0){
as_bad("unknown .machine argument: %s", arch_name);
return;
}
if(arch_flag.cputype != md_cputype){
as_bad("invalid .machine argument: %s", arch_name);
}
else{
new_cpusubtype = cpusubtype_combine(md_cputype,
md_cpusubtype,
arch_flag.cpusubtype);
if(new_cpusubtype == -1){
as_bad(".machine argument: %s can not be combined "
"with previous .machine directives, -arch "
"arguments or machine specific instructions",
arch_name);
}
else{
archflag_cpusubtype = new_cpusubtype;
}
}
}
*input_line_pointer = c;
demand_empty_rest_of_line();
}
static
void
s_secure_log_reset(
uintptr_t value)
{
s_secure_log_used = FALSE;
demand_empty_rest_of_line();
}
static
void
s_secure_log_unique(
uintptr_t value)
{
FILE *secure_log_fp;
char *log_msg, c;
if(s_secure_log_used != FALSE)
as_fatal(".secure_log_unique specified multiple times");
if(secure_log_file == FALSE)
as_fatal(".secure_log_unique used but AS_SECURE_LOG_FILE "
"environment variable unset.");
log_msg = input_line_pointer;
do{
c = *input_line_pointer++;
} while(is_end_of_line(c) == FALSE);
*--input_line_pointer = 0;
if((secure_log_fp = fopen(secure_log_file, "a+"))){
char *file;
unsigned int line;
as_file_and_line(&file, &line);
fprintf(secure_log_fp, "%s:%d:%s\n",
(file != NULL) ? file : "unknown",
line, log_msg);
fclose(secure_log_fp);
}
else
as_fatal("couldn't write to secure log file: \"%s\"",
secure_log_file);
s_secure_log_used = TRUE;
*input_line_pointer = c;
demand_empty_rest_of_line();
}
int inlineasm_checks = 0;
char *inlineasm_file_name = NULL;
int inlineasm_line_number = 0;
int inlineasm_column_number = 0;
static
void
s_inlineasm(
uintptr_t value)
{
int length;
inlineasm_checks = value;
inlineasm_file_name = NULL;
inlineasm_line_number = 0;
inlineasm_column_number = 0;
SKIP_WHITESPACE();
if(value == 1 && *input_line_pointer == '"'){
if((inlineasm_file_name = demand_copy_string(&length))){
SKIP_WHITESPACE();
if(*input_line_pointer == ','){
input_line_pointer++;
inlineasm_line_number = get_absolute_expression();
SKIP_WHITESPACE();
if(*input_line_pointer == ','){
input_line_pointer++;
inlineasm_column_number = get_absolute_expression();
}
}
}
}
demand_empty_rest_of_line();
}
static
void
s_incbin(
uintptr_t value)
{
char *filename, *whole_file_name, *p;
int length;
FILE *fp;
int the_char;
if((filename = demand_copy_string( & length ) )) {
demand_empty_rest_of_line();
whole_file_name = find_an_include_file(filename);
if(whole_file_name != NULL &&
(fp = fopen(whole_file_name, "r"))){
do{
the_char = getc_unlocked(fp);
if (the_char != -1){
p = frag_more(1);
*p = the_char;
}
}while(the_char != -1);
fclose(fp);
return;
}
as_fatal("Couldn't find the .incbin file: \"%s\"", filename);
}
}
static
void
s_data_region(
uintptr_t value)
{
char *region_type, c;
c = *input_line_pointer;
if(c != '\n'){
region_type = input_line_pointer;
do{
c = *input_line_pointer++;
}while(c != '\n');
input_line_pointer--;
}
demand_empty_rest_of_line();
}
static
void
s_end_data_region(
uintptr_t value)
{
demand_empty_rest_of_line();
}
#ifdef SPARC
void
s_seg (ignore)
int ignore;
{
pseudo_typeS *ps_t;
char s[32];
printf("S_SEG\n");
if (strncmp (input_line_pointer, "\"text\"", 6) == 0)
{
input_line_pointer += 6;
(void)s_builtin_section(builtin_sections);
demand_empty_rest_of_line();
return;
}
if (strncmp (input_line_pointer, "\"data\"", 6) == 0)
{
input_line_pointer++;
strncpy(s, input_line_pointer, 4);
input_line_pointer += 5;
ps_t = (pseudo_typeS *) hash_find(po_hash, s);
if (ps_t == 0)
as_bad ("invalid .seg argument");
printf("INDEX %s, %p\n", s, (void *)ps_t->poc_val);
s_builtin_section ((const struct builtin_section *)ps_t->poc_val);
demand_empty_rest_of_line();
return;
}
as_bad ("Unknown segment type");
demand_empty_rest_of_line ();
}
#endif
#ifdef PPC
static
void
s_ppcasm_end(
uintptr_t value)
{
demand_empty_rest_of_line();
}
#endif
#ifndef ARCH64
static inline int
sizeof_sleb128_32 (int32_t value)
{
register int size = 0;
register unsigned byte;
do
{
byte = (value & 0x7f);
value = (value >> 7) | ~(-(offsetT)1 >> 7);
size += 1;
}
while (!(((value == 0) && ((byte & 0x40) == 0))
|| ((value == -1) && ((byte & 0x40) != 0))));
return size;
}
#endif
#ifdef ARCH64
static inline int
sizeof_sleb128_64 (int64_t value)
{
register int size = 0;
register unsigned byte;
do
{
byte = (value & 0x7f);
value = (value >> 7) | ~(-(offsetT)1 >> 7);
size += 1;
}
while (!(((value == 0) && ((byte & 0x40) == 0))
|| ((value == -1) && ((byte & 0x40) != 0))));
return size;
}
#endif
#ifndef ARCH64
static inline int
sizeof_uleb128_32 (uint32_t value)
{
register int size = 0;
register unsigned byte;
do
{
byte = (value & 0x7f);
value >>= 7;
size += 1;
}
while (value != 0);
return size;
}
#endif
#ifdef ARCH64
static inline int
sizeof_uleb128_64 (uint64_t value)
{
register int size = 0;
register unsigned byte;
do
{
byte = (value & 0x7f);
value >>= 7;
size += 1;
}
while (value != 0);
return size;
}
#endif
#ifdef ARCH64
int
sizeof_leb128 (valueT value, int sign)
{
if (sign)
return sizeof_sleb128_64 ((offsetT) value);
else
return sizeof_uleb128_64 (value);
}
#else
int
sizeof_leb128 (valueT value, int sign)
{
if (sign)
return sizeof_sleb128_32 ((offsetT) value);
else
return sizeof_uleb128_32 (value);
}
#endif
static inline int
output_sleb128 (char *p, offsetT value)
{
register char *orig = p;
register int more;
do
{
unsigned byte = (value & 0x7f);
value = (value >> 7) | ~(-(offsetT)1 >> 7);
more = !((((value == 0) && ((byte & 0x40) == 0))
|| ((value == -1) && ((byte & 0x40) != 0))));
if (more)
byte |= 0x80;
*p++ = byte;
}
while (more);
return p - orig;
}
static inline int
output_uleb128 (char *p, valueT value)
{
char *orig = p;
do
{
unsigned byte = (value & 0x7f);
value >>= 7;
if (value != 0)
byte |= 0x80;
*p++ = byte;
}
while (value != 0);
return p - orig;
}
int
output_leb128 (char *p, valueT value, int sign)
{
if (sign)
return output_sleb128 (p, (offsetT) value);
else
return output_uleb128 (p, value);
}