#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 "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"
char *input_line_pointer = NULL;
char *buffer_limit = NULL;
#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
};
#define _ (0)
static
#ifndef PPC
const
#endif
char is_end_of_line[256] = {
99, _, _, _, _, _, _, _, _, _,99, _, _, _, _, _,
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
_, _, _, _, _, _, _, _, _, _, _,99, _, _, _, _,
#if defined(M88K) || defined(PPC) || defined(HPPA)
99, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
#else
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
#endif
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _,
_, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _
};
#undef _
#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 char *write_macro(char *string, char *value);
static char *write_symbol(char *string, char *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 },
{ "literal_pointers", S_LITERAL_POINTERS },
{ "non_lazy_symbol_pointers", S_NON_LAZY_SYMBOL_POINTERS },
{ "lazy_symbol_pointers", S_LAZY_SYMBOL_POINTERS },
{ "symbol_stubs", S_SYMBOL_STUBS },
{ "mod_init_funcs", S_MOD_INIT_FUNC_POINTERS },
{ "mod_term_funcs", S_MOD_TERM_FUNC_POINTERS },
{ "coalesced", S_COALESCED },
{ 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 },
{ 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" },
{ "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 },
{ "constructor", "__TEXT", "__constructor" },
{ "destructor", "__TEXT", "__destructor" },
{ "fvmlib_init0", "__TEXT", "__fvmlib_init0" },
{ "fvmlib_init1", "__TEXT", "__fvmlib_init1" },
{ "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
},
{ "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
},
{ "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 },
{ "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" },
{ "objc_meta_class", "__OBJC", "__meta_class" },
{ "objc_string_object", "__OBJC", "__string_object" },
{ "objc_protocol", "__OBJC", "__protocol" },
{ "objc_cat_cls_meth", "__OBJC", "__cat_cls_meth" },
{ "objc_cat_inst_meth", "__OBJC", "__cat_inst_meth" },
{ "objc_cls_meth", "__OBJC", "__cls_meth" },
{ "objc_inst_meth", "__OBJC", "__inst_meth" },
{ "objc_message_refs", "__OBJC", "__message_refs", S_LITERAL_POINTERS, 2},
{ "objc_cls_refs", "__OBJC", "__cls_refs", S_LITERAL_POINTERS, 2},
{ "objc_class_names", "__TEXT", "__cstring", S_CSTRING_LITERALS },
{ "objc_module_info", "__OBJC", "__module_info" },
{ "objc_symbols", "__OBJC", "__symbols" },
{ "objc_category", "__OBJC", "__category" },
{ "objc_meth_var_types", "__TEXT", "__cstring", S_CSTRING_LITERALS },
{ "objc_class_vars", "__OBJC", "__class_vars" },
{ "objc_instance_vars", "__OBJC", "__instance_vars" },
{ "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);
static void s_indirect_symbol(int value);
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_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);
#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},
{ "indirect_symbol", s_indirect_symbol, 0},
{ "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 },
{ "lsym", s_lsym, 0 },
{ "section", s_section, 0 },
{ "zerofill", s_zerofill, 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' },
{ "reference",s_reference, 0 },
{ "lazy_reference",s_lazy_reference, 0 },
{ "weak_reference",s_weak_reference, 0 },
{ "weak_definition",s_weak_definition, 0 },
{ "include", s_include, 0 },
{ "macro", s_macro, 0 },
{ "endmacro", 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 },
{ NULL }
};
#ifdef PPC
static const pseudo_typeS ppcasm_pseudo_table[] = {
{ "include", s_include, 0 },
{ "end", s_ppcasm_end, 0 },
{ NULL }
};
#endif
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[(int)'\r'] = 99;
is_end_of_line[(int)'@'] = 0;
is_end_of_line[(int)':'] = 0;
ppcasm_pseudo_op_begin();
}
#endif
static
void
pseudo_op_begin(
void)
{
char *errtxt;
const pseudo_typeS *pop;
unsigned long i;
pseudo_typeS *sections_pseudo_table;
po_hash = hash_new();
errtxt = "";
for(pop = pseudo_table; pop->poc_name && *errtxt == '\0'; pop++)
errtxt = hash_insert(po_hash, pop->poc_name, (char *)pop);
for(pop = md_pseudo_table; pop->poc_name && *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 == '\0';
pop++)
errtxt = hash_insert(po_hash, pop->poc_name, (char *)pop);
if(*errtxt != '\0'){
as_fatal("error constructing pseudo-op table (%s)", errtxt);
}
}
#ifdef PPC
static
void
ppcasm_pseudo_op_begin(
void)
{
char *errtxt, *uppercase;
const pseudo_typeS *pop;
unsigned long len, i;
ppcasm_po_hash = hash_new();
errtxt = "";
for(pop = ppcasm_pseudo_table; pop->poc_name != NULL; pop++){
errtxt = hash_insert(ppcasm_po_hash, pop->poc_name, (char *)pop);
if(*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 != '\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_warn("file contains unmatched .ifs or .elses");
if(macro_name != NULL)
as_warn("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_warn ("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[(int)*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[(int)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_warn("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_warn("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[(int)*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[(int)c]){
input_line_pointer++;
continue;
}
as_warn("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(scrub_from_string, scrub_to_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[(int)*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_warn("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 ++;
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;
int temp;
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 != ','){
as_warn("Expected comma after symbol-name");
ignore_rest_of_line();
return;
}
input_line_pointer++;
if((temp = get_absolute_expression ()) < 0){
as_warn(".COMMon length (%d.) <0! Ignored.", temp);
ignore_rest_of_line();
return;
}
*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 != 0) {
as_warn("Ignoring attempt to re-define symbol");
ignore_rest_of_line();
return;
}
if(symbolP->sy_value != 0){
if(symbolP->sy_value != (unsigned long)temp)
as_warn("Length of .comm \"%s\" is already %ld. Not changed "
"to %d.", symbolP->sy_name, symbolP->sy_value, temp);
}
else{
symbolP -> sy_value = temp;
symbolP -> sy_type |= N_EXT;
}
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_warn("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_warn("Expect comma after rep-size in .fill");
ignore_rest_of_line();
return;
}
if(get_absolute_expression_and_terminator(&temp_size) != ','){
input_line_pointer--;
as_warn("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_warn(".fill size clamped to %d.", BSD_FILL_SIZE_CROCK_8);
temp_size = BSD_FILL_SIZE_CROCK_8 ;
}
if(temp_size < 0){
as_warn("Size negative: .fill ignored.");
temp_size = 0;
}
else if(temp_size != 0 &&
temp_size != 1 &&
temp_size != 2 &&
temp_size != 4){
as_warn(".fill size must be 0,1,2 or 4, .fill ignored");
temp_size = 0;
}
else if(temp_repeat <= 0){
as_warn(".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();
}
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_warn("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();
}
static
void
s_lcomm(
int value)
{
char *name;
char c;
char *p;
int 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_warn("Expected comma after name");
ignore_rest_of_line();
return;
}
input_line_pointer ++;
if((size = get_absolute_expression()) < 0){
as_warn("BSS length (%d.) <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_warn("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_warn("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_warn("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_warn("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_warn("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_warn("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);
*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_warn("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_warn("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 ||
(s->flags & SECTION_TYPE) == S_MOD_INIT_FUNC_POINTERS ||
(s->flags & SECTION_TYPE) == S_MOD_TERM_FUNC_POINTERS ||
(s->flags & SECTION_ATTRIBUTES) != 0)
as_fatal("incompatible feature used: directive .%s (must "
"specify \"-dynamic\" to be used)", s->directive);
}
if(flagseen['k'] && s == builtin_sections){
frcP = section_new(s->segname, s->sectname,
s->flags & SECTION_TYPE,
(s->flags & SECTION_ATTRIBUTES) |
S_ATTR_PURE_INSTRUCTIONS,
s->sizeof_stub);
}
else{
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;
struct section 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_warn("Expected comma after segment-name");
ignore_rest_of_line();
return;
}
p = input_line_pointer - 1;
sectname = input_line_pointer;
do{
d = *input_line_pointer++ ;
}while(d != ',' && d != '\0' && d != '\n');
if(p + 1 == input_line_pointer){
as_warn("Expected section-name after comma");
ignore_rest_of_line();
return;
}
q = input_line_pointer - 1;
*p = 0;
if(strlen(segname) > sizeof(s.segname)){
as_warn("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_warn("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 != ',' && e != '\0' && e != '\n');
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_warn("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 != '\0' && f != '\n' && 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_warn("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(g != '\0' && g != '\n');
u = input_line_pointer - 1;
*u = 0;
sizeof_stub = strtoul(sizeof_stub_name, &endp, 0);
if(*endp != '\0'){
as_warn("size of stub section: %s not a proper "
"number", sizeof_stub_name);
ignore_rest_of_line();
return;
}
*u = g;
}
else{
as_warn("missing size of stub section (%s,%s)", segname,
sectname);
ignore_rest_of_line();
return;
}
}
}
else if(type == S_SYMBOL_STUBS){
as_warn("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;
struct section 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_warn("Expected comma after segment-name");
ignore_rest_of_line();
return;
}
p = input_line_pointer - 1;
sectname = input_line_pointer;
do{
d = *input_line_pointer++ ;
}while(d != ',' && d != '\0' && d != '\n');
if(p + 1 == input_line_pointer){
as_warn("Expected section-name after comma");
ignore_rest_of_line();
return;
}
q = input_line_pointer - 1;
*p = 0;
if(strlen(segname) > sizeof(s.segname)){
as_warn("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_warn("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_warn("Expected comma after symbol-name");
ignore_rest_of_line();
return;
}
input_line_pointer ++;
if((size = get_absolute_expression()) < 0){
as_warn("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);
symbolP->sy_other = frcP->frch_nsect;
symbolP->sy_frag = frcP->frch_root;
frcP->frch_root->fr_address += size;
}
else
as_warn("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);
*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;
*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_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[(int)*input_line_pointer])
input_line_pointer++;
else
ignore_rest_of_line();
}
void
ignore_rest_of_line(
void)
{
if(!is_end_of_line[(int)*input_line_pointer]){
as_warn("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[(int)*input_line_pointer])
input_line_pointer++;
}
input_line_pointer++;
know(is_end_of_line[(int)(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_warn("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_warn("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_warn("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_warn( "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);
segment = expression(&exp);
switch(segment){
case SEG_BIG:
as_warn("%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_warn("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 &&
exp.X_add_symbol->sy_other == exp.X_subtract_symbol->sy_other){
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_warn("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;
long mask;
long unmask;
long get;
long use;
char *p;
segT segment;
expressionS exp;
if(nbytes >= (int)sizeof(long int))
mask = 0;
else
mask = ~0 << (BITS_PER_CHAR * nbytes);
unmask = ~mask;
if(is_it_end_of_statement()){
c = 0;
input_line_pointer++;
}
else
c = ',';
while(c == ','){
segment = expression(&exp);
if(segment == SEG_DIFFSECT && exp.X_add_symbol == NULL){
as_warn("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:
as_warn("%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_warn("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_warn("Value x%x truncated to x%x.", (unsigned int)get,
(unsigned int)use);
}
md_number_to_chars(p, use, nbytes);
break;
case SEG_DIFFSECT:
case SEG_UNKNOWN:
case SEG_SECT:
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);
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_warn("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_warn("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 != '\0'){
as_warn( "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_warn("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 '"':
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_warn( "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_warn("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_warn("Symbols \"%s\" \"%s\" are undefined: absolute 0 "
"assumed.", name1, name2);
}
else{
as_warn("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);
}
long
get_absolute_expression(
void)
{
expressionS exp;
segT s;
s = expression(&exp);
if(s != SEG_ABSOLUTE){
if(s != SEG_NONE){
as_warn("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_warn("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_warn("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[(int)*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_warn("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(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[(int)*input_line_pointer]){
while(input_line_pointer < buffer_limit &&
!is_end_of_line[(int)*input_line_pointer]){
input_line_pointer ++;
}
}
input_line_pointer++;
know(is_end_of_line[(int)(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_warn("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_warn("Missing name of macro");
if(*macro_name == '.'){
pop = (pseudo_typeS *)hash_find(po_hash, macro_name + 1);
if(pop != NULL)
as_warn("Pseudo-op name: %s can't be a macro name",
macro_name);
}
}
totally_ignore_line();
}
void
s_endmacro(
int value)
{
char *errorString;
if(!macro_name){
as_warn ("This .endmacro does not match with a preceeding .macro");
ignore_rest_of_line();
}
else{
obstack_1grow(¯os, '\0');
errorString = hash_insert(ma_hash, macro_name,
obstack_finish(¯os));
if(*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');
obstack_1grow(¯os, c);
}while((c != ':') && !(is_end_of_line[(int)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 macro's 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[(int)c])
arguments[index] = NULL;
else{
int parenthesis_depth = 0;
do{
c = *input_line_pointer++;
if(parenthesis_depth){
if(c == ')')
parenthesis_depth --;
}
else{
if(c == '(')
parenthesis_depth ++;
else
if(is_end_of_line[(int)c] ||
(c == ' ') || (c == ','))
break;
}
know(c != '\0');
if(is_end_of_line[(int)c])
as_warn("missmatched parenthesis");
obstack_1grow(¯os, c);
}while(1);
obstack_1grow(¯os, '\0');
arguments[index] = obstack_finish(¯os);
nargs++;
if(is_end_of_line[(int)c])
--input_line_pointer;
else if(c == ' ')
if(*input_line_pointer == ',')
input_line_pointer++;
}
}
if(!is_end_of_line[(int)c]){
as_warn("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_apply(ma_hash, write_macro);
fwrite(null_string, 1, 1, dump_fp);
hash_apply(sy_hash, write_symbol);
fwrite(null_string, 1, 1, dump_fp);
fclose(dump_fp);
}
else
as_warn("couldn't write to dump file: \"%s\"", filename);
}
}
static
char *
write_macro(
char *string,
char *value)
{
know(string);
know(value);
know(strlen(string));
fwrite(string, (strlen(string) + 1), 1, dump_fp);
fwrite(value, (strlen(value) + 1), 1, dump_fp);
return(NULL);
}
static
char *
write_symbol(
char *string,
char *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);
}
return(NULL);
}
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(dump_fp);
obstack_1grow(¯os, the_char);
}while(the_char);
char_pointer = obstack_finish (¯os);
if(!(*char_pointer))
break;
do{
the_char = getc(dump_fp);
obstack_1grow(¯os, the_char);
}while(the_char);
if(*hash_insert(ma_hash, char_pointer,
obstack_finish(¯os)))
as_warn("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(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(dump_fp);
*char_pointer++ = getc(dump_fp);
*char_pointer++ = getc(dump_fp);
*char_pointer++ = getc(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);
}
}
#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