#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/round.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
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 pseudo_set(symbolS *symbolP);
static void stab(int what);
static char get_absolute_expression_and_terminator(long *val_pointer);
static char *demand_copy_C_string(int *len_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
unsigned long 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 },
{ 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;
unsigned long flags;
unsigned long default_align;
unsigned long 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" },
{ "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);
static void s_org(int value);
#endif
static void s_private_extern(int value);
#if !(defined(I386) && defined(ARCH64))
static void s_indirect_symbol(int value);
#endif
static void s_abort(int value);
static void s_comm(int value);
static void s_desc(int value);
static void s_file(int value);
static void s_fill(int value);
static void s_lcomm(int value);
static void s_lsym(int value);
static void s_set(int value);
static void s_reference(int value);
static void s_lazy_reference(int value);
static void s_weak_reference(int value);
static void s_weak_definition(int value);
static void s_no_dead_strip(int value);
static void s_include(int value);
static void s_dump(int value);
static void s_load(int value);
static void s_if(int value);
static void s_elseif(int value);
static void s_else(int value);
static void s_endif(int value);
static void s_macros_on(int value);
static void s_macros_off(int value);
static void s_section(int value);
static void s_zerofill(int value);
static unsigned long s_builtin_section(const struct builtin_section *s);
static void s_subsections_via_symbols(int value);
static void s_machine(int value);
static void s_secure_log_unique(int value);
static void s_secure_log_reset(int value);
#ifdef PPC
static void s_ppcasm_end(int value);
#endif
static const pseudo_typeS pseudo_table[] = {
#if !defined(I860)
{ "align", s_align, 1 },
{ "align32", s_align, 4 },
{ "p2align", s_align, 1 },
{ "p2alignw", s_align, 2 },
{ "p2alignl", s_align, 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' },
{ "file", s_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, 0 },
{ "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 },
{ "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 },
{ "no_dead_strip",s_no_dead_strip, 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 },
{ 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((long)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;
unsigned long 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 (*)(int))s_builtin_section;
sections_pseudo_table[i].poc_val = (int)(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;
unsigned long 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);
}
}
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 digit_value;
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);
#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)){
digit_value = c - '0';
if(*input_line_pointer++ == ':' ){
local_colon(digit_value);
}
else{
as_bad("Spurious digit %d.", digit_value);
input_line_pointer--;
ignore_rest_of_line();
}
continue;
}
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);
*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(
int 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(
int fill_size)
{
int power_of_2_alignment;
long 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 = get_absolute_expression();
#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
;
}
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 <
(unsigned long)power_of_2_alignment)
frchain_now->frch_section.align = power_of_2_alignment;
demand_empty_rest_of_line();
}
#endif
static
void
s_comm(
int 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 != (unsigned long)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(
int 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();
}
static
void
s_file(
int 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(
int value)
{
long temp_repeat;
long temp_size;
long 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){
as_bad(".fill size must be 0,1,2 or 4, .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(
int 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(
int 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(
int value)
{
char *name;
int c;
unsigned long 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(
int 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 = round(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 < (unsigned long)align)
bss->frch_section.align = align;
}
else
as_bad("Ignoring attempt to re-define symbol.");
demand_empty_rest_of_line();
}
void
s_line(
int value)
{
new_logical_line((char *)NULL, (int)(get_absolute_expression()) - 1);
demand_empty_rest_of_line();
}
static
void
s_lsym(
int 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(
int value)
{
segT segment;
expressionS exp;
long 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(
int 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(
int 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(
int value)
{
long temp_repeat;
long 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
unsigned long
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(
int value)
{
char *segname, *sectname, *typename;
char c, d, e, *p, *q, *r;
struct type_name *type_name;
unsigned long type, attribute;
section_t s;
frchainS *frcP;
unsigned long 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(
int value)
{
char *segname, *sectname, c, d, *p, *q, *name;
section_t s;
frchainS *frcP;
symbolS *symbolP;
int size, align;
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();
*p = c;
*q = d;
return;
}
frcP = section_new(segname, sectname, S_ZEROFILL, 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((size = get_absolute_expression()) < 0){
as_bad("zerofill size (%d.) <0! Ignored.", 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 < (unsigned long)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 = round(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(
int 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(
int 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(
int 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(
int 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);
if((symbolP->sy_type & N_TYPE) != N_UNDF &&
((symbolP->sy_type & N_TYPE) != N_SECT ||
is_section_coalesced(symbolP->sy_other) == FALSE))
as_fatal("symbol: %s can't be a weak_definition (currently "
"only supported in section of type coalesced)", name);
symbolP->sy_desc |= N_WEAK_DEF;
*p = c;
demand_empty_rest_of_line();
}
static
void
s_no_dead_strip(
int 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_include(
int 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 (int 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(
int what)
{
symbolS *symbolP;
char *string;
int saved_type;
int length;
int goof;
long 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( 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();
}
static
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
as_bad("Complex expression. Absolute segment assumed." );
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;
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(
int nbytes)
{
char c;
signed_expr_t
mask,
unmask,
get,
use;
char *p;
segT segment;
expressionS 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(long long))){
int i;
long long 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, (long)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);
}
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
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);
#endif
break;
default:
BAD_CASE(segment);
break;
}
c = *input_line_pointer++;
}
input_line_pointer--;
demand_empty_rest_of_line();
}
#ifdef M68K
void
big_cons(
int nbytes)
{
char c;
int radix;
long 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{
long 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)
{
long 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(
int 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();
}
void
stringer(
int 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;
long 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(
long *val_pointer)
{
*val_pointer = get_absolute_expression();
return(*input_line_pointer++);
}
static
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){
obstack_1grow(¬es, c);
len++;
}
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(
int 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(
int 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(
int 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(
int 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(
int value)
{
macros_on = TRUE;
demand_empty_rest_of_line();
}
void
s_macros_off(
int value)
{
macros_on = FALSE;
demand_empty_rest_of_line();
}
void
s_macro(
int 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 ++))
obstack_1grow (¯os, c);
obstack_1grow(¯os, '\0');
--input_line_pointer;
macro_name = obstack_finish(¯os);
if(macro_name == "")
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(
int value)
{
const char *errorString;
if(!macro_name){
as_bad ("This .endmacro does not match with a preceding .macro");
ignore_rest_of_line();
}
else{
obstack_1grow(¯os, '\0');
errorString = hash_insert(ma_hash, macro_name,
obstack_finish(¯os));
if(errorString != NULL && *errorString)
as_bad("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');
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");
obstack_1grow(¯os, c);
}while(1);
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();
}
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 ++))
obstack_1grow (¯os, c);
}
macro_contents = last_input_line_pointer;
continue;
}
else if (*macro_contents == 'n'){
macro_contents++ ;
obstack_1grow(¯os, nargs + '0');
continue;
}
}
obstack_1grow (¯os, c);
}
obstack_1grow (¯os, '\n');
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(
int 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(
int 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);
obstack_1grow(¯os, the_char);
}while(the_char);
char_pointer = obstack_finish (¯os);
if(!(*char_pointer))
break;
do{
the_char = getc_unlocked(dump_fp);
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);
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(
int value)
{
demand_empty_rest_of_line();
subsections_via_symbols = TRUE;
}
static
void
s_machine(
int value)
{
char *arch_name, c;
struct arch_flag arch_flag;
cpu_subtype_t new_cpusubtype;
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){
if(get_arch_from_flag(arch_name, &arch_flag) == 0){
as_bad("unknown .machine argument: %s", arch_name);
}
else{
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(
int value)
{
s_secure_log_used = FALSE;
demand_empty_rest_of_line();
}
static
void
s_secure_log_unique(
int 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();
}
#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, %d\n", s, 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(
int value)
{
demand_empty_rest_of_line();
}
#endif