#if 0
#define MASK_CHAR (0xFF)
#else
#define MASK_CHAR ((int)(unsigned char) -1)
#endif
#define MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT (16)
#include "as.h"
#include "safe-ctype.h"
#include "subsegs.h"
#include "sb.h"
#include "macro.h"
#include "obstack.h"
#include "listing.h"
#include "ecoff.h"
#include "dw2gencfi.h"
#ifndef TC_START_LABEL
#define TC_START_LABEL(x,y) (x == ':')
#endif
#ifndef TC_IMPLICIT_LCOMM_ALIGNMENT
#define TC_IMPLICIT_LCOMM_ALIGNMENT(SIZE, P2VAR) \
do \
{ \
if ((SIZE) >= 8) \
(P2VAR) = 3; \
else if ((SIZE) >= 4) \
(P2VAR) = 2; \
else if ((SIZE) >= 2) \
(P2VAR) = 1; \
else \
(P2VAR) = 0; \
} \
while (0)
#endif
char *input_line_pointer;
#if BITS_PER_CHAR != 8
die horribly;
#endif
#ifndef LEX_AT
#define LEX_AT 0
#endif
#ifndef LEX_BR
#define LEX_BR 0
#endif
#ifndef LEX_PCT
#define LEX_PCT 0
#endif
#ifndef LEX_QM
#define LEX_QM 0
#endif
#ifndef LEX_HASH
#define LEX_HASH 0
#endif
#ifndef LEX_DOLLAR
#define LEX_DOLLAR 3
#endif
#ifndef LEX_TILDE
#define LEX_TILDE 0
#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, LEX_HASH, LEX_DOLLAR, LEX_PCT, 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, LEX_QM,
LEX_AT, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, LEX_BR, 0, LEX_BR, 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, LEX_BR, 0, LEX_BR, LEX_TILDE, 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,
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3
};
char is_end_of_line[256] = {
#ifdef CR_EOL
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0,
#else
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 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,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
#ifndef TC_CASE_SENSITIVE
char original_case_string[128];
#endif
static char *buffer;
static char *buffer_limit;
int target_big_endian = TARGET_BYTES_BIG_ENDIAN;
char **include_dirs;
int include_dir_count;
int include_dir_maxlen = 1;
#ifndef WORKING_DOT_WORD
struct broken_word *broken_words;
int new_broken_words;
#endif
addressT abs_section_offset;
symbolS *line_label;
symbolS *mri_common_symbol;
static int mri_pending_align;
#ifndef NO_LISTING
#ifdef OBJ_ELF
static int dwarf_file_string;
#endif
#endif
static void do_align (int, char *, int, int);
static void s_align (int, int);
static int hex_float (int, char *);
static segT get_known_segmented_expression (expressionS * expP);
static void pobegin (void);
static int get_line_sb (sb *);
static void generate_file_debug (void);
void
read_begin (void)
{
const char *p;
pobegin ();
obj_read_begin_hook ();
obstack_begin (¬es, chunksize);
obstack_begin (&cond_obstack, chunksize);
for (p = line_separator_chars; *p; p++)
is_end_of_line[(unsigned char) *p] = 1;
if (flag_mri)
lex_type['?'] = 3;
}
static struct hash_control *po_hash;
static const pseudo_typeS potable[] = {
{"abort", s_abort, 0},
{"align", s_align_ptwo, 0},
{"ascii", stringer, 0},
{"asciz", stringer, 1},
{"balign", s_align_bytes, 0},
{"balignw", s_align_bytes, -2},
{"balignl", s_align_bytes, -4},
{"byte", cons, 1},
{"comm", s_comm, 0},
{"common", s_mri_common, 0},
{"common.s", s_mri_common, 1},
{"data", s_data, 0},
{"dc", cons, 2},
{"dc.b", cons, 1},
{"dc.d", float_cons, 'd'},
{"dc.l", cons, 4},
{"dc.s", float_cons, 'f'},
{"dc.w", cons, 2},
{"dc.x", float_cons, 'x'},
{"dcb", s_space, 2},
{"dcb.b", s_space, 1},
{"dcb.d", s_float_space, 'd'},
{"dcb.l", s_space, 4},
{"dcb.s", s_float_space, 'f'},
{"dcb.w", s_space, 2},
{"dcb.x", s_float_space, 'x'},
{"ds", s_space, 2},
{"ds.b", s_space, 1},
{"ds.d", s_space, 8},
{"ds.l", s_space, 4},
{"ds.p", s_space, 12},
{"ds.s", s_space, 4},
{"ds.w", s_space, 2},
{"ds.x", s_space, 12},
{"debug", s_ignore, 0},
#ifdef S_SET_DESC
{"desc", s_desc, 0},
#endif
{"double", float_cons, 'd'},
{"eject", listing_eject, 0},
{"else", s_else, 0},
{"elsec", s_else, 0},
{"elseif", s_elseif, (int) O_ne},
{"end", s_end, 0},
{"endc", s_endif, 0},
{"endfunc", s_func, 1},
{"endif", s_endif, 0},
{"endr", s_bad_endr, 0},
{"equ", s_set, 0},
{"equiv", s_set, 1},
{"err", s_err, 0},
{"exitm", s_mexit, 0},
{"extern", s_ignore, 0},
{"appfile", s_app_file, 1},
{"appline", s_app_line, 0},
{"fail", s_fail, 0},
{"file", s_app_file, 0},
{"fill", s_fill, 0},
{"float", float_cons, 'f'},
{"format", s_ignore, 0},
{"func", s_func, 0},
{"global", s_globl, 0},
{"globl", s_globl, 0},
{"hword", cons, 2},
{"if", s_if, (int) O_ne},
{"ifc", s_ifc, 0},
{"ifdef", s_ifdef, 0},
{"ifeq", s_if, (int) O_eq},
{"ifeqs", s_ifeqs, 0},
{"ifge", s_if, (int) O_ge},
{"ifgt", s_if, (int) O_gt},
{"ifle", s_if, (int) O_le},
{"iflt", s_if, (int) O_lt},
{"ifnc", s_ifc, 1},
{"ifndef", s_ifdef, 1},
{"ifne", s_if, (int) O_ne},
{"ifnes", s_ifeqs, 1},
{"ifnotdef", s_ifdef, 1},
{"incbin", s_incbin, 0},
{"include", s_include, 0},
{"int", cons, 4},
{"irp", s_irp, 0},
{"irep", s_irp, 0},
{"irpc", s_irp, 1},
{"irepc", s_irp, 1},
{"lcomm", s_lcomm, 0},
{"lflags", listing_flags, 0},
{"linkonce", s_linkonce, 0},
{"list", listing_list, 1},
{"llen", listing_psize, 1},
{"long", cons, 4},
{"lsym", s_lsym, 0},
{"macro", s_macro, 0},
{"mexit", s_mexit, 0},
{"mri", s_mri, 0},
{".mri", s_mri, 0},
{"name", s_ignore, 0},
{"noformat", s_ignore, 0},
{"nolist", listing_list, 0},
{"nopage", listing_nopage, 0},
{"octa", cons, 16},
{"offset", s_struct, 0},
{"org", s_org, 0},
{"p2align", s_align_ptwo, 0},
{"p2alignw", s_align_ptwo, -2},
{"p2alignl", s_align_ptwo, -4},
{"page", listing_eject, 0},
{"plen", listing_psize, 0},
{"print", s_print, 0},
{"psize", listing_psize, 0},
{"purgem", s_purgem, 0},
{"quad", cons, 8},
{"rep", s_rept, 0},
{"rept", s_rept, 0},
{"rva", s_rva, 4},
{"sbttl", listing_title, 1},
{"set", s_set, 0},
{"short", cons, 2},
{"single", float_cons, 'f'},
{"space", s_space, 0},
{"skip", s_space, 0},
{"sleb128", s_leb128, 1},
{"spc", s_ignore, 0},
{"stabd", s_stab, 'd'},
{"stabn", s_stab, 'n'},
{"stabs", s_stab, 's'},
{"string", stringer, 1},
{"struct", s_struct, 0},
{"text", s_text, 0},
{"this_GCC_requires_the_GNU_assembler", s_ignore, 0},
{"this_gcc_requires_the_gnu_assembler", s_ignore, 0},
{"title", listing_title, 0},
{"ttl", listing_title, 0},
{"uleb128", s_leb128, 0},
{"xcom", s_comm, 0},
{"xdef", s_globl, 0},
{"xref", s_ignore, 0},
{"xstabs", s_xstab, 's'},
{"word", cons, 2},
{"zero", s_space, 0},
{NULL, NULL, 0}
};
static int pop_override_ok = 0;
static const char *pop_table_name;
void
pop_insert (const pseudo_typeS *table)
{
const char *errtxt;
const pseudo_typeS *pop;
for (pop = table; pop->poc_name; pop++)
{
errtxt = hash_insert (po_hash, pop->poc_name, (char *) pop);
if (errtxt && (!pop_override_ok || strcmp (errtxt, "exists")))
as_fatal (_("error constructing %s pseudo-op table: %s"), pop_table_name,
errtxt);
}
}
#ifndef md_pop_insert
#define md_pop_insert() pop_insert(md_pseudo_table)
#endif
#ifndef obj_pop_insert
#define obj_pop_insert() pop_insert(obj_pseudo_table)
#endif
#ifndef cfi_pop_insert
#define cfi_pop_insert() pop_insert(cfi_pseudo_table)
#endif
static void
pobegin (void)
{
po_hash = hash_new ();
pop_table_name = "md";
md_pop_insert ();
pop_table_name = "obj";
pop_override_ok = 1;
obj_pop_insert ();
pop_table_name = "standard";
pop_insert (potable);
#ifdef TARGET_USE_CFIPOP
pop_table_name = "cfi";
pop_override_ok = 1;
cfi_pop_insert ();
#endif
}
#define HANDLE_CONDITIONAL_ASSEMBLY() \
if (ignore_input ()) \
{ \
while (!is_end_of_line[(unsigned char) *input_line_pointer++]) \
if (input_line_pointer == buffer_limit) \
break; \
continue; \
}
static char *scrub_string;
static char *scrub_string_end;
static int
scrub_from_string (char *buf, int buflen)
{
int copy;
copy = scrub_string_end - scrub_string;
if (copy > buflen)
copy = buflen;
memcpy (buf, scrub_string, copy);
scrub_string += copy;
return copy;
}
void
read_a_source_file (char *name)
{
register char c;
register char *s;
register int temp;
pseudo_typeS *pop;
#ifdef WARN_COMMENTS
found_comment = 0;
#endif
buffer = input_scrub_new_file (name);
listing_file (name);
listing_newline (NULL);
register_dependency (name);
generate_file_debug ();
while ((buffer_limit = input_scrub_next_buffer (&input_line_pointer)) != 0)
{
know (buffer_limit[-1] == '\n');
while (input_line_pointer < buffer_limit)
{
if (is_end_of_line[(unsigned char) input_line_pointer[-1]])
{
#ifdef md_start_line_hook
md_start_line_hook ();
#endif
if (input_line_pointer[-1] == '\n')
bump_line_counters ();
line_label = NULL;
if (LABELS_WITHOUT_COLONS || flag_m68k_mri)
{
if (is_name_beginner (*input_line_pointer))
{
char *line_start = input_line_pointer;
char c;
int mri_line_macro;
LISTING_NEWLINE ();
HANDLE_CONDITIONAL_ASSEMBLY ();
c = get_symbol_end ();
mri_line_macro = 0;
if (flag_m68k_mri)
{
char *rest = input_line_pointer + 1;
if (*rest == ':')
++rest;
if (*rest == ' ' || *rest == '\t')
++rest;
if ((strncasecmp (rest, "EQU", 3) == 0
|| strncasecmp (rest, "SET", 3) == 0)
&& (rest[3] == ' ' || rest[3] == '\t'))
{
input_line_pointer = rest + 3;
equals (line_start,
strncasecmp (rest, "SET", 3) == 0);
continue;
}
if (strncasecmp (rest, "MACRO", 5) == 0
&& (rest[5] == ' '
|| rest[5] == '\t'
|| is_end_of_line[(unsigned char) rest[5]]))
mri_line_macro = 1;
}
if (!mri_line_macro
#ifdef TC_START_LABEL_WITHOUT_COLON
&& TC_START_LABEL_WITHOUT_COLON(c,
input_line_pointer)
#endif
)
line_label = colon (line_start);
else
line_label = symbol_create (line_start,
absolute_section,
(valueT) 0,
&zero_address_frag);
*input_line_pointer = c;
if (c == ':')
input_line_pointer++;
}
}
}
if ((c = *input_line_pointer++) == '\t'
|| c == ' '
|| c == '\f'
|| c == 0)
c = *input_line_pointer++;
know (c != ' ');
#ifndef NO_LISTING
if (listing)
{
if ((listing & LISTING_MACEXP) && macro_nest > 0)
{
char *copy;
int len;
for (s = input_line_pointer - 1; *s; ++s)
if (is_end_of_line[(unsigned char) *s])
break;
len = s - (input_line_pointer - 1);
copy = (char *) xmalloc (len + macro_nest + 2);
memset (copy, '>', macro_nest);
copy[macro_nest] = ' ';
memcpy (copy + macro_nest + 1, input_line_pointer - 1, len);
copy[macro_nest + 1 + len] = '\0';
listing_newline (copy);
}
else
listing_newline (NULL);
}
#endif
if (is_name_beginner (c))
{
HANDLE_CONDITIONAL_ASSEMBLY ();
s = --input_line_pointer;
c = get_symbol_end ();
if (TC_START_LABEL (c, input_line_pointer))
{
if (flag_m68k_mri)
{
char *rest = input_line_pointer + 1;
if (*rest == ':')
++rest;
if (*rest == ' ' || *rest == '\t')
++rest;
if ((strncasecmp (rest, "EQU", 3) == 0
|| strncasecmp (rest, "SET", 3) == 0)
&& (rest[3] == ' ' || rest[3] == '\t'))
{
input_line_pointer = rest + 3;
equals (s, 1);
continue;
}
}
line_label = colon (s);
*input_line_pointer++ = ':';
#ifdef tc_check_label
tc_check_label (line_label);
#endif
SKIP_WHITESPACE ();
}
else if (c == '='
|| ((c == ' ' || c == '\t')
&& input_line_pointer[1] == '='
#ifdef TC_EQUAL_IN_INSN
&& !TC_EQUAL_IN_INSN (c, input_line_pointer)
#endif
))
{
equals (s, 1);
demand_empty_rest_of_line ();
}
else
{
pop = NULL;
#ifndef TC_CASE_SENSITIVE
{
char *s2 = s;
strncpy (original_case_string, s2, sizeof (original_case_string));
original_case_string[sizeof (original_case_string) - 1] = 0;
while (*s2)
{
*s2 = TOLOWER (*s2);
s2++;
}
}
#endif
if (NO_PSEUDO_DOT || flag_m68k_mri)
{
pop = (pseudo_typeS *) hash_find (po_hash, s);
if (pop != NULL && pop->poc_handler == NULL)
pop = NULL;
}
if (pop != NULL
|| (!flag_m68k_mri && *s == '.'))
{
if (pop == NULL)
pop = (pseudo_typeS *) hash_find (po_hash, s + 1);
if (pop && !pop->poc_handler)
pop = NULL;
if (mri_pending_align
&& (pop == NULL
|| !((pop->poc_handler == cons
&& pop->poc_val == 1)
|| (pop->poc_handler == s_space
&& pop->poc_val == 1)
#ifdef tc_conditional_pseudoop
|| tc_conditional_pseudoop (pop)
#endif
|| pop->poc_handler == s_if
|| pop->poc_handler == s_ifdef
|| pop->poc_handler == s_ifc
|| pop->poc_handler == s_ifeqs
|| pop->poc_handler == s_else
|| pop->poc_handler == s_endif
|| pop->poc_handler == s_globl
|| pop->poc_handler == s_ignore)))
{
do_align (1, (char *) NULL, 0, 0);
mri_pending_align = 0;
if (line_label != NULL)
{
symbol_set_frag (line_label, frag_now);
S_SET_VALUE (line_label, frag_now_fix ());
}
}
if (pop == NULL)
{
as_bad (_("unknown pseudo-op: `%s'"), s);
*input_line_pointer = c;
s_ignore (0);
continue;
}
*input_line_pointer = c;
if (c == ' ' || c == '\t')
input_line_pointer++;
(*pop->poc_handler) (pop->poc_val);
if (pop->poc_handler == s_end)
goto quit;
}
else
{
int inquote = 0;
#ifdef QUOTES_IN_INSN
int inescape = 0;
#endif
*input_line_pointer = c;
while (!is_end_of_line[(unsigned char) *input_line_pointer]
|| inquote
#ifdef TC_EOL_IN_INSN
|| TC_EOL_IN_INSN (input_line_pointer)
#endif
)
{
if (flag_m68k_mri && *input_line_pointer == '\'')
inquote = !inquote;
#ifdef QUOTES_IN_INSN
if (inescape)
inescape = 0;
else if (*input_line_pointer == '"')
inquote = !inquote;
else if (*input_line_pointer == '\\')
inescape = 1;
#endif
input_line_pointer++;
}
c = *input_line_pointer;
*input_line_pointer = '\0';
generate_lineno_debug ();
if (macro_defined)
{
sb out;
const char *err;
macro_entry *macro;
if (check_macro (s, &out, &err, ¯o))
{
if (err != NULL)
as_bad ("%s", err);
*input_line_pointer++ = c;
input_scrub_include_sb (&out,
input_line_pointer, 1);
sb_kill (&out);
buffer_limit =
input_scrub_next_buffer (&input_line_pointer);
#ifdef md_macro_info
md_macro_info (macro);
#endif
continue;
}
}
if (mri_pending_align)
{
do_align (1, (char *) NULL, 0, 0);
mri_pending_align = 0;
if (line_label != NULL)
{
symbol_set_frag (line_label, frag_now);
S_SET_VALUE (line_label, frag_now_fix ());
}
}
md_assemble (s);
*input_line_pointer++ = c;
}
}
continue;
}
if (is_end_of_line[(unsigned char) c])
continue;
if ((LOCAL_LABELS_DOLLAR || LOCAL_LABELS_FB) && ISDIGIT (c))
{
char *backup = input_line_pointer;
HANDLE_CONDITIONAL_ASSEMBLY ();
temp = c - '0';
while (ISDIGIT (*input_line_pointer))
{
temp = (temp * 10) + *input_line_pointer - '0';
++input_line_pointer;
}
if (LOCAL_LABELS_DOLLAR
&& *input_line_pointer == '$'
&& *(input_line_pointer + 1) == ':')
{
input_line_pointer += 2;
if (dollar_label_defined (temp))
{
as_fatal (_("label \"%d$\" redefined"), temp);
}
define_dollar_label (temp);
colon (dollar_label_name (temp, 0));
continue;
}
if (LOCAL_LABELS_FB
&& *input_line_pointer++ == ':')
{
fb_label_instance_inc (temp);
colon (fb_label_name (temp, 0));
continue;
}
input_line_pointer = backup;
}
if (c && strchr (line_comment_chars, c))
{
sb sbuf;
char *ends;
char *new_buf;
char *new_tmp;
unsigned int new_length;
char *tmp_buf = 0;
bump_line_counters ();
s = input_line_pointer;
if (strncmp (s, "APP\n", 4))
continue;
s += 4;
sb_new (&sbuf);
ends = strstr (s, "#NO_APP\n");
if (!ends)
{
unsigned int tmp_len;
unsigned int num;
tmp_len = buffer_limit - s;
tmp_buf = xmalloc (tmp_len + 1);
memcpy (tmp_buf, s, tmp_len);
do
{
new_tmp = input_scrub_next_buffer (&buffer);
if (!new_tmp)
break;
else
buffer_limit = new_tmp;
input_line_pointer = buffer;
ends = strstr (buffer, "#NO_APP\n");
if (ends)
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);
input_line_pointer = ends ? ends + 8 : NULL;
s = tmp_buf;
ends = s + tmp_len;
}
else
{
input_line_pointer = ends + 8;
}
scrub_string = s;
scrub_string_end = ends;
new_length = ends - s;
new_buf = (char *) xmalloc (new_length);
new_tmp = new_buf;
for (;;)
{
int space;
int size;
space = (new_buf + new_length) - new_tmp;
size = do_scrub_chars (scrub_from_string, new_tmp, space);
if (size < space)
{
new_tmp[size] = 0;
break;
}
new_buf = xrealloc (new_buf, new_length + 100);
new_tmp = new_buf + new_length;
new_length += 100;
}
if (tmp_buf)
free (tmp_buf);
sb_add_string (&sbuf, new_buf);
input_scrub_include_sb (&sbuf, input_line_pointer, 0);
sb_kill (&sbuf);
buffer_limit = input_scrub_next_buffer (&input_line_pointer);
free (new_buf);
continue;
}
HANDLE_CONDITIONAL_ASSEMBLY ();
#ifdef tc_unrecognized_line
if (tc_unrecognized_line (c))
continue;
#endif
input_line_pointer--;
demand_empty_rest_of_line ();
}
#ifdef md_after_pass_hook
md_after_pass_hook ();
#endif
}
quit:
#ifdef md_cleanup
md_cleanup ();
#endif
input_scrub_close ();
#ifdef WARN_COMMENTS
{
if (warn_comment && found_comment)
as_warn_where (found_comment_file, found_comment,
"first comment found here");
}
#endif
}
char *
mri_comment_field (char *stopcp)
{
char *s;
#ifdef TC_M68K
int inquote = 0;
know (flag_m68k_mri);
for (s = input_line_pointer;
((!is_end_of_line[(unsigned char) *s] && *s != ' ' && *s != '\t')
|| inquote);
s++)
{
if (*s == '\'')
inquote = !inquote;
}
#else
for (s = input_line_pointer;
!is_end_of_line[(unsigned char) *s];
s++)
;
#endif
*stopcp = *s;
*s = '\0';
return s;
}
void
mri_comment_end (char *stop, int stopc)
{
know (flag_mri);
input_line_pointer = stop;
*stop = stopc;
while (!is_end_of_line[(unsigned char) *input_line_pointer])
++input_line_pointer;
}
void
s_abort (int ignore ATTRIBUTE_UNUSED)
{
as_fatal (_(".abort detected. Abandoning ship."));
}
static void
do_align (int n, char *fill, int len, int max)
{
if (now_seg == absolute_section)
{
if (fill != NULL)
while (len-- > 0)
if (*fill++ != '\0')
{
as_warn (_("ignoring fill value in absolute section"));
break;
}
fill = NULL;
len = 0;
}
#ifdef md_flush_pending_output
md_flush_pending_output ();
#endif
#ifdef md_do_align
md_do_align (n, fill, len, max, just_record_alignment);
#endif
if (n != 0 && !need_pass_2)
{
if (fill == NULL)
{
if (subseg_text_p (now_seg))
frag_align_code (n, max);
else
frag_align (n, 0, max);
}
else if (len <= 1)
frag_align (n, *fill, max);
else
frag_align_pattern (n, fill, len, max);
}
#ifdef md_do_align
just_record_alignment: ATTRIBUTE_UNUSED_LABEL
#endif
record_alignment (now_seg, n - OCTETS_PER_BYTE_POWER);
}
static void
s_align (int arg, int bytes_p)
{
register unsigned int align;
char *stop = NULL;
char stopc;
offsetT fill = 0;
int max;
int fill_p;
if (flag_mri)
stop = mri_comment_field (&stopc);
if (is_end_of_line[(unsigned char) *input_line_pointer])
{
if (arg < 0)
align = 0;
else
align = arg;
}
else
{
align = get_absolute_expression ();
SKIP_WHITESPACE ();
}
if (bytes_p)
{
if (align != 0)
{
unsigned int i;
for (i = 0; (align & 1) == 0; align >>= 1, ++i)
;
if (align != 1)
as_bad (_("alignment not a power of 2"));
align = i;
}
}
if (align > 15)
{
align = 15;
as_warn (_("alignment too large: %u assumed"), align);
}
if (*input_line_pointer != ',')
{
fill_p = 0;
max = 0;
}
else
{
++input_line_pointer;
if (*input_line_pointer == ',')
fill_p = 0;
else
{
fill = get_absolute_expression ();
SKIP_WHITESPACE ();
fill_p = 1;
}
if (*input_line_pointer != ',')
max = 0;
else
{
++input_line_pointer;
max = get_absolute_expression ();
}
}
if (!fill_p)
{
if (arg < 0)
as_warn (_("expected fill pattern missing"));
do_align (align, (char *) NULL, 0, max);
}
else
{
int fill_len;
if (arg >= 0)
fill_len = 1;
else
fill_len = -arg;
if (fill_len <= 1)
{
char fill_char;
fill_char = fill;
do_align (align, &fill_char, fill_len, max);
}
else
{
char ab[16];
if ((size_t) fill_len > sizeof ab)
abort ();
md_number_to_chars (ab, fill, fill_len);
do_align (align, ab, fill_len, max);
}
}
demand_empty_rest_of_line ();
if (flag_mri)
mri_comment_end (stop, stopc);
}
void
s_align_bytes (int arg)
{
s_align (arg, 1);
}
void
s_align_ptwo (int arg)
{
s_align (arg, 0);
}
symbolS *
s_comm_internal (int param,
symbolS *(*comm_parse_extra) (int, symbolS *, addressT))
{
char *name;
char c;
char *p;
offsetT temp, size;
symbolS *symbolP = NULL;
char *stop = NULL;
char stopc;
expressionS exp;
if (flag_mri)
stop = mri_comment_field (&stopc);
name = input_line_pointer;
c = get_symbol_end ();
p = input_line_pointer;
*p = c;
if (name == p)
{
as_bad (_("expected symbol name"));
discard_rest_of_line ();
goto out;
}
SKIP_WHITESPACE ();
if (*input_line_pointer == ',')
input_line_pointer++;
*p = 0;
temp = get_absolute_expr (&exp);
size = temp;
#ifdef BFD_ASSEMBLER
size &= ((offsetT) 2 << (stdoutput->arch_info->bits_per_address - 1)) - 1;
#endif
if (exp.X_op == O_absent)
{
as_bad (_("missing size expression"));
*p = c;
ignore_rest_of_line ();
goto out;
}
else if (temp != size || !exp.X_unsigned)
{
as_warn (_("size (%ld) out of range, ignored"), (long) temp);
*p = c;
ignore_rest_of_line ();
goto out;
}
symbolP = symbol_find_or_make (name);
if (S_IS_DEFINED (symbolP) && !S_IS_COMMON (symbolP))
{
symbolP = NULL;
as_bad (_("symbol `%s' is already defined"), name);
*p = c;
ignore_rest_of_line ();
goto out;
}
size = S_GET_VALUE (symbolP);
if (size == 0)
size = temp;
else if (size != temp)
as_warn (_("size of \"%s\" is already %ld; not changing to %ld"),
name, (long) size, (long) temp);
*p = c;
if (comm_parse_extra != NULL)
symbolP = (*comm_parse_extra) (param, symbolP, size);
else
{
S_SET_VALUE (symbolP, (valueT) size);
S_SET_EXTERNAL (symbolP);
#ifdef OBJ_VMS
{
extern int flag_one;
if (size == 0 || !flag_one)
S_GET_OTHER (symbolP) = const_flag;
}
#endif
}
know (symbolP == NULL || symbolP->sy_frag == &zero_address_frag);
demand_empty_rest_of_line ();
out:
if (flag_mri)
mri_comment_end (stop, stopc);
return symbolP;
}
void
s_comm (int ignore)
{
s_comm_internal (ignore, NULL);
}
void
s_mri_common (int small ATTRIBUTE_UNUSED)
{
char *name;
char c;
char *alc = NULL;
symbolS *sym;
offsetT align;
char *stop = NULL;
char stopc;
if (!flag_mri)
{
s_comm (0);
return;
}
stop = mri_comment_field (&stopc);
SKIP_WHITESPACE ();
name = input_line_pointer;
if (!ISDIGIT (*name))
c = get_symbol_end ();
else
{
do
{
++input_line_pointer;
}
while (ISDIGIT (*input_line_pointer));
c = *input_line_pointer;
*input_line_pointer = '\0';
if (line_label != NULL)
{
alc = (char *) xmalloc (strlen (S_GET_NAME (line_label))
+ (input_line_pointer - name)
+ 1);
sprintf (alc, "%s%s", name, S_GET_NAME (line_label));
name = alc;
}
}
sym = symbol_find_or_make (name);
*input_line_pointer = c;
if (alc != NULL)
free (alc);
if (*input_line_pointer != ',')
align = 0;
else
{
++input_line_pointer;
align = get_absolute_expression ();
}
if (S_IS_DEFINED (sym) && !S_IS_COMMON (sym))
{
as_bad (_("symbol `%s' is already defined"), S_GET_NAME (sym));
ignore_rest_of_line ();
mri_comment_end (stop, stopc);
return;
}
S_SET_EXTERNAL (sym);
mri_common_symbol = sym;
#ifdef S_SET_ALIGN
if (align != 0)
S_SET_ALIGN (sym, align);
#endif
if (line_label != NULL)
{
expressionS exp;
exp.X_op = O_symbol;
exp.X_add_symbol = sym;
exp.X_add_number = 0;
symbol_set_value_expression (line_label, &exp);
symbol_set_frag (line_label, &zero_address_frag);
S_SET_SEGMENT (line_label, expr_section);
}
if (*input_line_pointer == ',')
input_line_pointer += 2;
if (*input_line_pointer == ',')
input_line_pointer += 2;
demand_empty_rest_of_line ();
mri_comment_end (stop, stopc);
}
void
s_data (int ignore ATTRIBUTE_UNUSED)
{
segT section;
register int temp;
temp = get_absolute_expression ();
if (flag_readonly_data_in_text)
{
section = text_section;
temp += 1000;
}
else
section = data_section;
subseg_set (section, (subsegT) temp);
#ifdef OBJ_VMS
const_flag = 0;
#endif
demand_empty_rest_of_line ();
}
void
s_app_file_string (char *file)
{
#ifdef LISTING
if (listing)
listing_source_file (file);
#endif
register_dependency (file);
#ifdef obj_app_file
obj_app_file (file);
#endif
}
void
s_app_file (int appfile)
{
register char *s;
int length;
if ((s = demand_copy_string (&length)) != 0)
{
int may_omit
= (!new_logical_line (s, appfile ? -2 : -1) && appfile);
if (flag_m68k_mri
&& *input_line_pointer == '\''
&& is_end_of_line[(unsigned char) input_line_pointer[1]])
++input_line_pointer;
demand_empty_rest_of_line ();
if (!may_omit)
s_app_file_string (s);
}
}
void
s_app_line (int ignore ATTRIBUTE_UNUSED)
{
int l;
l = get_absolute_expression () - 1;
if (l < 0)
as_warn (_("line numbers must be positive; line number %d rejected"),
l + 1);
else
{
new_logical_line ((char *) NULL, l);
#ifdef LISTING
if (listing)
listing_source_line (l);
#endif
}
demand_empty_rest_of_line ();
}
void
s_end (int ignore ATTRIBUTE_UNUSED)
{
if (flag_mri)
{
SKIP_WHITESPACE ();
if (!is_end_of_line[(unsigned char) *input_line_pointer]
&& *input_line_pointer != '*'
&& *input_line_pointer != '!')
as_warn (_("start address not supported"));
}
}
void
s_err (int ignore ATTRIBUTE_UNUSED)
{
as_bad (_(".err encountered"));
demand_empty_rest_of_line ();
}
void
s_fail (int ignore ATTRIBUTE_UNUSED)
{
offsetT temp;
char *stop = NULL;
char stopc;
if (flag_mri)
stop = mri_comment_field (&stopc);
temp = get_absolute_expression ();
if (temp >= 500)
as_warn (_(".fail %ld encountered"), (long) temp);
else
as_bad (_(".fail %ld encountered"), (long) temp);
demand_empty_rest_of_line ();
if (flag_mri)
mri_comment_end (stop, stopc);
}
void
s_fill (int ignore ATTRIBUTE_UNUSED)
{
expressionS rep_exp;
long size = 1;
register long fill = 0;
char *p;
#ifdef md_flush_pending_output
md_flush_pending_output ();
#endif
get_known_segmented_expression (&rep_exp);
if (*input_line_pointer == ',')
{
input_line_pointer++;
size = get_absolute_expression ();
if (*input_line_pointer == ',')
{
input_line_pointer++;
fill = get_absolute_expression ();
}
}
#define BSD_FILL_SIZE_CROCK_8 (8)
if (size > BSD_FILL_SIZE_CROCK_8)
{
as_warn (_(".fill size clamped to %d"), BSD_FILL_SIZE_CROCK_8);
size = BSD_FILL_SIZE_CROCK_8;
}
if (size < 0)
{
as_warn (_("size negative; .fill ignored"));
size = 0;
}
else if (rep_exp.X_op == O_constant && rep_exp.X_add_number <= 0)
{
if (rep_exp.X_add_number < 0)
as_warn (_("repeat < 0; .fill ignored"));
size = 0;
}
if (size && !need_pass_2)
{
if (rep_exp.X_op == O_constant)
{
p = frag_var (rs_fill, (int) size, (int) size,
(relax_substateT) 0, (symbolS *) 0,
(offsetT) rep_exp.X_add_number,
(char *) 0);
}
else
{
symbolS *rep_sym;
rep_sym = make_expr_symbol (&rep_exp);
if (size != 1)
{
expressionS size_exp;
size_exp.X_op = O_constant;
size_exp.X_add_number = size;
rep_exp.X_op = O_multiply;
rep_exp.X_add_symbol = rep_sym;
rep_exp.X_op_symbol = make_expr_symbol (&size_exp);
rep_exp.X_add_number = 0;
rep_sym = make_expr_symbol (&rep_exp);
}
p = frag_var (rs_space, (int) size, (int) size,
(relax_substateT) 0, rep_sym, (offsetT) 0, (char *) 0);
}
memset (p, 0, (unsigned int) size);
#define BSD_FILL_SIZE_CROCK_4 (4)
md_number_to_chars (p, (valueT) fill,
(size > BSD_FILL_SIZE_CROCK_4
? BSD_FILL_SIZE_CROCK_4
: (int) size));
}
demand_empty_rest_of_line ();
}
void
s_globl (int ignore ATTRIBUTE_UNUSED)
{
char *name;
int c;
symbolS *symbolP;
char *stop = NULL;
char stopc;
if (flag_mri)
stop = mri_comment_field (&stopc);
do
{
name = input_line_pointer;
c = get_symbol_end ();
symbolP = symbol_find_or_make (name);
S_SET_EXTERNAL (symbolP);
*input_line_pointer = c;
SKIP_WHITESPACE ();
c = *input_line_pointer;
if (c == ',')
{
input_line_pointer++;
SKIP_WHITESPACE ();
if (is_end_of_line[(unsigned char) *input_line_pointer])
c = '\n';
}
}
while (c == ',');
demand_empty_rest_of_line ();
if (flag_mri)
mri_comment_end (stop, stopc);
}
void
s_irp (int irpc)
{
char *file;
unsigned int line;
sb s;
const char *err;
sb out;
as_where (&file, &line);
sb_new (&s);
while (!is_end_of_line[(unsigned char) *input_line_pointer])
sb_add_char (&s, *input_line_pointer++);
sb_new (&out);
err = expand_irp (irpc, 0, &s, &out, get_line_sb);
if (err != NULL)
as_bad_where (file, line, "%s", err);
sb_kill (&s);
input_scrub_include_sb (&out, input_line_pointer, 1);
sb_kill (&out);
buffer_limit = input_scrub_next_buffer (&input_line_pointer);
}
void
s_linkonce (int ignore ATTRIBUTE_UNUSED)
{
enum linkonce_type type;
SKIP_WHITESPACE ();
type = LINKONCE_DISCARD;
if (!is_end_of_line[(unsigned char) *input_line_pointer])
{
char *s;
char c;
s = input_line_pointer;
c = get_symbol_end ();
if (strcasecmp (s, "discard") == 0)
type = LINKONCE_DISCARD;
else if (strcasecmp (s, "one_only") == 0)
type = LINKONCE_ONE_ONLY;
else if (strcasecmp (s, "same_size") == 0)
type = LINKONCE_SAME_SIZE;
else if (strcasecmp (s, "same_contents") == 0)
type = LINKONCE_SAME_CONTENTS;
else
as_warn (_("unrecognized .linkonce type `%s'"), s);
*input_line_pointer = c;
}
#ifdef obj_handle_link_once
obj_handle_link_once (type);
#else
#ifdef BFD_ASSEMBLER
{
flagword flags;
if ((bfd_applicable_section_flags (stdoutput) & SEC_LINK_ONCE) == 0)
as_warn (_(".linkonce is not supported for this object file format"));
flags = bfd_get_section_flags (stdoutput, now_seg);
flags |= SEC_LINK_ONCE;
switch (type)
{
default:
abort ();
case LINKONCE_DISCARD:
flags |= SEC_LINK_DUPLICATES_DISCARD;
break;
case LINKONCE_ONE_ONLY:
flags |= SEC_LINK_DUPLICATES_ONE_ONLY;
break;
case LINKONCE_SAME_SIZE:
flags |= SEC_LINK_DUPLICATES_SAME_SIZE;
break;
case LINKONCE_SAME_CONTENTS:
flags |= SEC_LINK_DUPLICATES_SAME_CONTENTS;
break;
}
if (!bfd_set_section_flags (stdoutput, now_seg, flags))
as_bad (_("bfd_set_section_flags: %s"),
bfd_errmsg (bfd_get_error ()));
}
#else
as_warn (_(".linkonce is not supported for this object file format"));
#endif
#endif
demand_empty_rest_of_line ();
}
void
bss_alloc (symbolS *symbolP, addressT size, int align)
{
char *pfrag;
segT current_seg = now_seg;
subsegT current_subseg = now_subseg;
segT bss_seg = bss_section;
#if defined (TC_MIPS) || defined (TC_ALPHA)
if (OUTPUT_FLAVOR == bfd_target_ecoff_flavour
|| OUTPUT_FLAVOR == bfd_target_elf_flavour)
{
if (size <= bfd_get_gp_size (stdoutput))
{
bss_seg = subseg_new (".sbss", 1);
seg_info (bss_seg)->bss = 1;
#ifdef BFD_ASSEMBLER
if (!bfd_set_section_flags (stdoutput, bss_seg, SEC_ALLOC))
as_warn (_("error setting flags for \".sbss\": %s"),
bfd_errmsg (bfd_get_error ()));
#endif
}
}
#endif
subseg_set (bss_seg, 1);
if (align)
{
record_alignment (bss_seg, align);
frag_align (align, 0, 0);
}
if (S_GET_SEGMENT (symbolP) == bss_seg)
symbol_get_frag (symbolP)->fr_symbol = NULL;
symbol_set_frag (symbolP, frag_now);
pfrag = frag_var (rs_org, 1, 1, 0, symbolP, size, NULL);
*pfrag = 0;
#ifdef S_SET_SIZE
S_SET_SIZE (symbolP, size);
#endif
S_SET_SEGMENT (symbolP, bss_seg);
#ifdef OBJ_COFF
if (S_GET_STORAGE_CLASS (symbolP) != C_EXT)
S_SET_STORAGE_CLASS (symbolP, C_STAT);
#endif
subseg_set (current_seg, current_subseg);
}
offsetT
parse_align (int align_bytes)
{
expressionS exp;
addressT align;
SKIP_WHITESPACE ();
if (*input_line_pointer != ',')
{
no_align:
as_bad (_("expected alignment after size"));
ignore_rest_of_line ();
return -1;
}
input_line_pointer++;
SKIP_WHITESPACE ();
align = get_absolute_expr (&exp);
if (exp.X_op == O_absent)
goto no_align;
if (!exp.X_unsigned)
{
as_warn (_("alignment negative; 0 assumed"));
align = 0;
}
if (align_bytes && align != 0)
{
unsigned int alignp2 = 0;
while ((align & 1) == 0)
align >>= 1, ++alignp2;
if (align != 1)
{
as_bad (_("alignment not a power of 2"));
ignore_rest_of_line ();
return -1;
}
align = alignp2;
}
return align;
}
symbolS *
s_lcomm_internal (int needs_align, symbolS *symbolP, addressT size)
{
addressT align = 0;
if (needs_align)
{
align = parse_align (needs_align - 1);
if (align == (addressT) -1)
return NULL;
}
else
TC_IMPLICIT_LCOMM_ALIGNMENT (size, align);
bss_alloc (symbolP, size, align);
return symbolP;
}
void
s_lcomm (int needs_align)
{
s_comm_internal (needs_align, s_lcomm_internal);
}
void
s_lcomm_bytes (int needs_align)
{
s_comm_internal (needs_align * 2, s_lcomm_internal);
}
void
s_lsym (int ignore ATTRIBUTE_UNUSED)
{
register char *name;
register char c;
register char *p;
expressionS exp;
register symbolS *symbolP;
name = input_line_pointer;
c = get_symbol_end ();
p = input_line_pointer;
*p = c;
if (name == p)
{
as_bad (_("expected symbol name"));
discard_rest_of_line ();
return;
}
SKIP_WHITESPACE ();
if (*input_line_pointer != ',')
{
*p = 0;
as_bad (_("expected comma after \"%s\""), name);
*p = c;
ignore_rest_of_line ();
return;
}
input_line_pointer++;
expression (&exp);
if (exp.X_op != O_constant
&& exp.X_op != O_register)
{
as_bad (_("bad expression"));
ignore_rest_of_line ();
return;
}
*p = 0;
symbolP = symbol_find_or_make (name);
if (S_GET_SEGMENT (symbolP) == undefined_section
&& S_GET_VALUE (symbolP) == 0)
{
S_SET_SEGMENT (symbolP,
(exp.X_op == O_constant
? absolute_section
: reg_section));
S_SET_VALUE (symbolP, (valueT) exp.X_add_number);
}
else
{
as_bad (_("symbol `%s' is already defined"), name);
}
*p = c;
demand_empty_rest_of_line ();
}
static int
get_line_sb (sb *line)
{
char quote1, quote2, inquote;
unsigned char c;
if (input_line_pointer[-1] == '\n')
bump_line_counters ();
if (input_line_pointer >= buffer_limit)
{
buffer_limit = input_scrub_next_buffer (&input_line_pointer);
if (buffer_limit == 0)
return 0;
}
if (!flag_m68k_mri)
quote1 = '"';
else
quote1 = '\0';
quote2 = '\0';
if (flag_m68k_mri)
quote2 = '\'';
#ifdef LEX_IS_STRINGQUOTE
quote2 = '\'';
#endif
inquote = '\0';
while ((c = * input_line_pointer ++) != 0
&& (!is_end_of_line[c]
|| (inquote != '\0' && c != '\n')))
{
if (inquote == c)
inquote = '\0';
else if (inquote == '\0')
{
if (c == quote1)
inquote = quote1;
else if (c == quote2)
inquote = quote2;
}
sb_add_char (line, c);
}
return c;
}
void
s_macro (int ignore ATTRIBUTE_UNUSED)
{
char *file;
unsigned int line;
sb s;
sb label;
const char *err;
const char *name;
as_where (&file, &line);
sb_new (&s);
while (!is_end_of_line[(unsigned char) *input_line_pointer])
sb_add_char (&s, *input_line_pointer++);
sb_new (&label);
if (line_label != NULL)
sb_add_string (&label, S_GET_NAME (line_label));
err = define_macro (0, &s, &label, get_line_sb, &name);
if (err != NULL)
as_bad_where (file, line, "%s", err);
else
{
if (line_label != NULL)
{
S_SET_SEGMENT (line_label, undefined_section);
S_SET_VALUE (line_label, 0);
symbol_set_frag (line_label, &zero_address_frag);
}
if (((NO_PSEUDO_DOT || flag_m68k_mri)
&& hash_find (po_hash, name) != NULL)
|| (!flag_m68k_mri
&& *name == '.'
&& hash_find (po_hash, name + 1) != NULL))
as_warn (_("attempt to redefine pseudo-op `%s' ignored"),
name);
}
sb_kill (&s);
}
void
s_mexit (int ignore ATTRIBUTE_UNUSED)
{
cond_exit_macro (macro_nest);
buffer_limit = input_scrub_next_buffer (&input_line_pointer);
}
void
s_mri (int ignore ATTRIBUTE_UNUSED)
{
int on, old_flag;
on = get_absolute_expression ();
old_flag = flag_mri;
if (on != 0)
{
flag_mri = 1;
#ifdef TC_M68K
flag_m68k_mri = 1;
#endif
macro_mri_mode (1);
}
else
{
flag_mri = 0;
#ifdef TC_M68K
flag_m68k_mri = 0;
#endif
macro_mri_mode (0);
}
expr_set_precedence ();
#ifdef MRI_MODE_CHANGE
if (on != old_flag)
MRI_MODE_CHANGE (on);
#endif
demand_empty_rest_of_line ();
}
static void
do_org (segT segment, expressionS *exp, int fill)
{
if (segment != now_seg && segment != absolute_section)
as_bad (_("invalid segment \"%s\""), segment_name (segment));
if (now_seg == absolute_section)
{
if (fill != 0)
as_warn (_("ignoring fill value in absolute section"));
if (exp->X_op != O_constant)
{
as_bad (_("only constant offsets supported in absolute section"));
exp->X_add_number = 0;
}
abs_section_offset = exp->X_add_number;
}
else
{
char *p;
symbolS *sym = exp->X_add_symbol;
offsetT off = exp->X_add_number * OCTETS_PER_BYTE;
if (exp->X_op != O_constant && exp->X_op != O_symbol)
{
sym = make_expr_symbol (exp);
off = 0;
}
p = frag_var (rs_org, 1, 1, (relax_substateT) 0, sym, off, (char *) 0);
*p = fill;
}
}
void
s_org (int ignore ATTRIBUTE_UNUSED)
{
register segT segment;
expressionS exp;
register long temp_fill;
#ifdef md_flush_pending_output
md_flush_pending_output ();
#endif
if (flag_m68k_mri)
{
as_bad (_("MRI style ORG pseudo-op not supported"));
ignore_rest_of_line ();
return;
}
segment = get_known_segmented_expression (&exp);
if (*input_line_pointer == ',')
{
input_line_pointer++;
temp_fill = get_absolute_expression ();
}
else
temp_fill = 0;
if (!need_pass_2)
do_org (segment, &exp, temp_fill);
demand_empty_rest_of_line ();
}
void
s_mri_sect (char *type ATTRIBUTE_UNUSED)
{
#ifdef TC_M68K
char *name;
char c;
segT seg;
SKIP_WHITESPACE ();
name = input_line_pointer;
if (!ISDIGIT (*name))
c = get_symbol_end ();
else
{
do
{
++input_line_pointer;
}
while (ISDIGIT (*input_line_pointer));
c = *input_line_pointer;
*input_line_pointer = '\0';
}
name = xstrdup (name);
*input_line_pointer = c;
seg = subseg_new (name, 0);
if (*input_line_pointer == ',')
{
int align;
++input_line_pointer;
align = get_absolute_expression ();
record_alignment (seg, align);
}
*type = 'C';
if (*input_line_pointer == ',')
{
c = *++input_line_pointer;
c = TOUPPER (c);
if (c == 'C' || c == 'D' || c == 'M' || c == 'R')
*type = c;
else
as_bad (_("unrecognized section type"));
++input_line_pointer;
#ifdef BFD_ASSEMBLER
{
flagword flags;
flags = SEC_NO_FLAGS;
if (*type == 'C')
flags = SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE;
else if (*type == 'D' || *type == 'M')
flags = SEC_ALLOC | SEC_LOAD | SEC_DATA;
else if (*type == 'R')
flags = SEC_ALLOC | SEC_LOAD | SEC_DATA | SEC_READONLY | SEC_ROM;
if (flags != SEC_NO_FLAGS)
{
if (!bfd_set_section_flags (stdoutput, seg, flags))
as_warn (_("error setting flags for \"%s\": %s"),
bfd_section_name (stdoutput, seg),
bfd_errmsg (bfd_get_error ()));
}
}
#endif
}
if (*input_line_pointer == ',')
input_line_pointer += 2;
demand_empty_rest_of_line ();
#else
#ifdef TC_I960
char *name;
char c;
segT seg;
SKIP_WHITESPACE ();
name = input_line_pointer;
c = get_symbol_end ();
name = xstrdup (name);
*input_line_pointer = c;
seg = subseg_new (name, 0);
if (*input_line_pointer != ',')
*type = 'C';
else
{
char *sectype;
++input_line_pointer;
SKIP_WHITESPACE ();
sectype = input_line_pointer;
c = get_symbol_end ();
if (*sectype == '\0')
*type = 'C';
else if (strcasecmp (sectype, "text") == 0)
*type = 'C';
else if (strcasecmp (sectype, "data") == 0)
*type = 'D';
else if (strcasecmp (sectype, "romdata") == 0)
*type = 'R';
else
as_warn (_("unrecognized section type `%s'"), sectype);
*input_line_pointer = c;
}
if (*input_line_pointer == ',')
{
char *seccmd;
++input_line_pointer;
SKIP_WHITESPACE ();
seccmd = input_line_pointer;
c = get_symbol_end ();
if (strcasecmp (seccmd, "absolute") == 0)
{
as_bad (_("absolute sections are not supported"));
*input_line_pointer = c;
ignore_rest_of_line ();
return;
}
else if (strcasecmp (seccmd, "align") == 0)
{
int align;
*input_line_pointer = c;
align = get_absolute_expression ();
record_alignment (seg, align);
}
else
{
as_warn (_("unrecognized section command `%s'"), seccmd);
*input_line_pointer = c;
}
}
demand_empty_rest_of_line ();
#else
as_bad ("MRI mode not supported for this target");
ignore_rest_of_line ();
#endif
#endif
}
void
s_print (int ignore ATTRIBUTE_UNUSED)
{
char *s;
int len;
s = demand_copy_C_string (&len);
if (s != NULL)
printf ("%s\n", s);
demand_empty_rest_of_line ();
}
void
s_purgem (int ignore ATTRIBUTE_UNUSED)
{
if (is_it_end_of_statement ())
{
demand_empty_rest_of_line ();
return;
}
do
{
char *name;
char c;
SKIP_WHITESPACE ();
name = input_line_pointer;
c = get_symbol_end ();
delete_macro (name);
*input_line_pointer = c;
SKIP_WHITESPACE ();
}
while (*input_line_pointer++ == ',');
--input_line_pointer;
demand_empty_rest_of_line ();
}
void
s_bad_endr (int ignore ATTRIBUTE_UNUSED)
{
as_warn (_(".endr encountered without preceeding .rept, .irc, or .irp"));
demand_empty_rest_of_line ();
}
void
s_rept (int ignore ATTRIBUTE_UNUSED)
{
int count;
count = get_absolute_expression ();
do_repeat (count, "REPT", "ENDR");
}
void
do_repeat (int count, const char *start, const char *end)
{
sb one;
sb many;
sb_new (&one);
if (!buffer_and_nest (start, end, &one, get_line_sb))
{
as_bad (_("%s without %s"), start, end);
return;
}
sb_new (&many);
while (count-- > 0)
sb_add_sb (&many, &one);
sb_kill (&one);
input_scrub_include_sb (&many, input_line_pointer, 1);
sb_kill (&many);
buffer_limit = input_scrub_next_buffer (&input_line_pointer);
}
void
end_repeat (int extra)
{
cond_exit_macro (macro_nest);
while (extra-- >= 0)
buffer_limit = input_scrub_next_buffer (&input_line_pointer);
}
void
s_set (int equiv)
{
register char *name;
register char delim;
register char *end_name;
register symbolS *symbolP;
name = input_line_pointer;
delim = get_symbol_end ();
end_name = input_line_pointer;
*end_name = delim;
if (name == end_name)
{
as_bad (_("expected symbol name"));
discard_rest_of_line ();
return;
}
SKIP_WHITESPACE ();
if (*input_line_pointer != ',')
{
*end_name = 0;
as_bad (_("expected comma after \"%s\""), name);
*end_name = delim;
ignore_rest_of_line ();
return;
}
input_line_pointer++;
*end_name = 0;
if (name[0] == '.' && name[1] == '\0')
{
register segT segment;
expressionS exp;
segment = get_known_segmented_expression (&exp);
if (!need_pass_2)
do_org (segment, &exp, 0);
*end_name = delim;
return;
}
if ((symbolP = symbol_find (name)) == NULL
&& (symbolP = md_undefined_symbol (name)) == NULL)
{
#ifndef NO_LISTING
if (listing & LISTING_SYMBOLS)
{
extern struct list_info_struct *listing_tail;
fragS *dummy_frag = (fragS *) xmalloc (sizeof (fragS));
memset (dummy_frag, 0, sizeof (fragS));
dummy_frag->fr_type = rs_fill;
dummy_frag->line = listing_tail;
symbolP = symbol_new (name, undefined_section, 0, dummy_frag);
dummy_frag->fr_symbol = symbolP;
}
else
#endif
symbolP = symbol_new (name, undefined_section, 0, &zero_address_frag);
#ifdef OBJ_COFF
SF_SET_LOCAL (symbolP);
#endif
}
symbol_table_insert (symbolP);
*end_name = delim;
if (equiv
&& S_IS_DEFINED (symbolP)
&& S_GET_SEGMENT (symbolP) != reg_section)
as_bad (_("symbol `%s' is already defined"), S_GET_NAME (symbolP));
pseudo_set (symbolP);
demand_empty_rest_of_line ();
}
void
s_space (int mult)
{
expressionS exp;
expressionS val;
char *p = 0;
char *stop = NULL;
char stopc;
int bytes;
#ifdef md_flush_pending_output
md_flush_pending_output ();
#endif
if (flag_mri)
stop = mri_comment_field (&stopc);
if (flag_m68k_mri && mult > 1)
{
if (now_seg == absolute_section)
{
abs_section_offset += abs_section_offset & 1;
if (line_label != NULL)
S_SET_VALUE (line_label, abs_section_offset);
}
else if (mri_common_symbol != NULL)
{
valueT val;
val = S_GET_VALUE (mri_common_symbol);
if ((val & 1) != 0)
{
S_SET_VALUE (mri_common_symbol, val + 1);
if (line_label != NULL)
{
expressionS *symexp;
symexp = symbol_get_value_expression (line_label);
know (symexp->X_op == O_symbol);
know (symexp->X_add_symbol == mri_common_symbol);
symexp->X_add_number += 1;
}
}
}
else
{
do_align (1, (char *) NULL, 0, 0);
if (line_label != NULL)
{
symbol_set_frag (line_label, frag_now);
S_SET_VALUE (line_label, frag_now_fix ());
}
}
}
bytes = mult;
expression (&exp);
SKIP_WHITESPACE ();
if (*input_line_pointer == ',')
{
++input_line_pointer;
expression (&val);
}
else
{
val.X_op = O_constant;
val.X_add_number = 0;
}
if (val.X_op != O_constant
|| val.X_add_number < - 0x80
|| val.X_add_number > 0xff
|| (mult != 0 && mult != 1 && val.X_add_number != 0))
{
if (exp.X_op != O_constant)
as_bad (_("unsupported variable size or fill value"));
else
{
offsetT i;
if (mult == 0)
mult = 1;
bytes = mult * exp.X_add_number;
for (i = 0; i < exp.X_add_number; i++)
emit_expr (&val, mult);
}
}
else
{
if (exp.X_op == O_constant)
{
long repeat;
repeat = exp.X_add_number;
if (mult)
repeat *= mult;
bytes = repeat;
if (repeat <= 0)
{
if (!flag_mri)
as_warn (_(".space repeat count is zero, ignored"));
else if (repeat < 0)
as_warn (_(".space repeat count is negative, ignored"));
goto getout;
}
if (now_seg == absolute_section)
{
abs_section_offset += repeat;
goto getout;
}
if (mri_common_symbol != NULL)
{
S_SET_VALUE (mri_common_symbol,
S_GET_VALUE (mri_common_symbol) + repeat);
goto getout;
}
if (!need_pass_2)
p = frag_var (rs_fill, 1, 1, (relax_substateT) 0, (symbolS *) 0,
(offsetT) repeat, (char *) 0);
}
else
{
if (now_seg == absolute_section)
{
as_bad (_("space allocation too complex in absolute section"));
subseg_set (text_section, 0);
}
if (mri_common_symbol != NULL)
{
as_bad (_("space allocation too complex in common section"));
mri_common_symbol = NULL;
}
if (!need_pass_2)
p = frag_var (rs_space, 1, 1, (relax_substateT) 0,
make_expr_symbol (&exp), (offsetT) 0, (char *) 0);
}
if (p)
*p = val.X_add_number;
}
getout:
if (flag_mri && (bytes & 1) != 0)
mri_pending_align = 1;
demand_empty_rest_of_line ();
if (flag_mri)
mri_comment_end (stop, stopc);
}
void
s_float_space (int float_type)
{
offsetT count;
int flen;
char temp[MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT];
char *stop = NULL;
char stopc;
if (flag_mri)
stop = mri_comment_field (&stopc);
count = get_absolute_expression ();
SKIP_WHITESPACE ();
if (*input_line_pointer != ',')
{
as_bad (_("missing value"));
ignore_rest_of_line ();
if (flag_mri)
mri_comment_end (stop, stopc);
return;
}
++input_line_pointer;
SKIP_WHITESPACE ();
if (input_line_pointer[0] == '0'
&& ISALPHA (input_line_pointer[1]))
input_line_pointer += 2;
if (input_line_pointer[0] == ':')
{
flen = hex_float (float_type, temp);
if (flen < 0)
{
ignore_rest_of_line ();
if (flag_mri)
mri_comment_end (stop, stopc);
return;
}
}
else
{
char *err;
err = md_atof (float_type, temp, &flen);
know (flen <= MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT);
know (flen > 0);
if (err)
{
as_bad (_("bad floating literal: %s"), err);
ignore_rest_of_line ();
if (flag_mri)
mri_comment_end (stop, stopc);
return;
}
}
while (--count >= 0)
{
char *p;
p = frag_more (flen);
memcpy (p, temp, (unsigned int) flen);
}
demand_empty_rest_of_line ();
if (flag_mri)
mri_comment_end (stop, stopc);
}
void
s_struct (int ignore ATTRIBUTE_UNUSED)
{
char *stop = NULL;
char stopc;
if (flag_mri)
stop = mri_comment_field (&stopc);
abs_section_offset = get_absolute_expression ();
subseg_set (absolute_section, 0);
demand_empty_rest_of_line ();
if (flag_mri)
mri_comment_end (stop, stopc);
}
void
s_text (int ignore ATTRIBUTE_UNUSED)
{
register int temp;
temp = get_absolute_expression ();
subseg_set (text_section, (subsegT) temp);
demand_empty_rest_of_line ();
#ifdef OBJ_VMS
const_flag &= ~IN_DEFAULT_SECTION;
#endif
}
void
demand_empty_rest_of_line (void)
{
SKIP_WHITESPACE ();
if (is_end_of_line[(unsigned char) *input_line_pointer])
input_line_pointer++;
else
{
if (ISPRINT (*input_line_pointer))
as_bad (_("junk at end of line, first unrecognized character is `%c'"),
*input_line_pointer);
else
as_bad (_("junk at end of line, first unrecognized character valued 0x%x"),
*input_line_pointer);
ignore_rest_of_line ();
}
know (is_end_of_line[(unsigned char) input_line_pointer[-1]]);
}
void
ignore_rest_of_line (void)
{
while (input_line_pointer < buffer_limit
&& !is_end_of_line[(unsigned char) *input_line_pointer])
input_line_pointer++;
input_line_pointer++;
know (is_end_of_line[(unsigned char) input_line_pointer[-1]]);
}
void
discard_rest_of_line (void)
{
while (input_line_pointer < buffer_limit
&& !is_end_of_line[(unsigned char) *input_line_pointer])
input_line_pointer++;
input_line_pointer++;
know (is_end_of_line[(unsigned char) input_line_pointer[-1]]);
}
void
pseudo_set (symbolS *symbolP)
{
expressionS exp;
#if (defined (OBJ_AOUT) || defined (OBJ_BOUT)) && ! defined (BFD_ASSEMBLER)
int ext;
#endif
know (symbolP);
#if (defined (OBJ_AOUT) || defined (OBJ_BOUT)) && ! defined (BFD_ASSEMBLER)
ext = S_IS_EXTERNAL (symbolP);
#endif
(void) expression (&exp);
if (exp.X_op == O_illegal)
as_bad (_("illegal expression"));
else if (exp.X_op == O_absent)
as_bad (_("missing expression"));
else if (exp.X_op == O_big)
{
if (exp.X_add_number > 0)
as_bad (_("bignum invalid"));
else
as_bad (_("floating point number invalid"));
}
else if (exp.X_op == O_subtract
&& SEG_NORMAL (S_GET_SEGMENT (exp.X_add_symbol))
&& (symbol_get_frag (exp.X_add_symbol)
== symbol_get_frag (exp.X_op_symbol)))
{
exp.X_op = O_constant;
exp.X_add_number = (S_GET_VALUE (exp.X_add_symbol)
- S_GET_VALUE (exp.X_op_symbol));
}
switch (exp.X_op)
{
case O_illegal:
case O_absent:
case O_big:
exp.X_add_number = 0;
case O_constant:
S_SET_SEGMENT (symbolP, absolute_section);
#if (defined (OBJ_AOUT) || defined (OBJ_BOUT)) && ! defined (BFD_ASSEMBLER)
if (ext)
S_SET_EXTERNAL (symbolP);
else
S_CLEAR_EXTERNAL (symbolP);
#endif
S_SET_VALUE (symbolP, (valueT) exp.X_add_number);
if (exp.X_op != O_constant)
symbol_set_frag (symbolP, &zero_address_frag);
break;
case O_register:
S_SET_SEGMENT (symbolP, reg_section);
S_SET_VALUE (symbolP, (valueT) exp.X_add_number);
symbol_set_frag (symbolP, &zero_address_frag);
break;
case O_symbol:
if (S_GET_SEGMENT (exp.X_add_symbol) == undefined_section
|| exp.X_add_number != 0)
symbol_set_value_expression (symbolP, &exp);
else if (symbol_section_p (symbolP))
as_bad ("attempt to set value of section symbol");
else
{
symbolS *s = exp.X_add_symbol;
S_SET_SEGMENT (symbolP, S_GET_SEGMENT (s));
#if (defined (OBJ_AOUT) || defined (OBJ_BOUT)) && ! defined (BFD_ASSEMBLER)
if (ext)
S_SET_EXTERNAL (symbolP);
else
S_CLEAR_EXTERNAL (symbolP);
#endif
S_SET_VALUE (symbolP,
exp.X_add_number + S_GET_VALUE (s));
symbol_set_frag (symbolP, symbol_get_frag (s));
copy_symbol_attributes (symbolP, s);
}
break;
default:
symbol_set_value_expression (symbolP, &exp);
break;
}
}
#ifdef TC_M68K
static void
parse_mri_cons (expressionS *exp, unsigned int nbytes);
#endif
#ifndef TC_PARSE_CONS_EXPRESSION
#ifdef BITFIELD_CONS_EXPRESSIONS
#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) parse_bitfield_cons (EXP, NBYTES)
static void
parse_bitfield_cons (expressionS *exp, unsigned int nbytes);
#endif
#ifdef REPEAT_CONS_EXPRESSIONS
#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) parse_repeat_cons (EXP, NBYTES)
static void
parse_repeat_cons (expressionS *exp, unsigned int nbytes);
#endif
#ifndef TC_PARSE_CONS_EXPRESSION
#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) expression (EXP)
#endif
#endif
void
do_parse_cons_expression (expressionS *exp,
int nbytes ATTRIBUTE_UNUSED)
{
TC_PARSE_CONS_EXPRESSION (exp, nbytes);
}
static void
cons_worker (register int nbytes,
int rva)
{
int c;
expressionS exp;
char *stop = NULL;
char stopc;
#ifdef md_flush_pending_output
md_flush_pending_output ();
#endif
if (flag_mri)
stop = mri_comment_field (&stopc);
if (is_it_end_of_statement ())
{
demand_empty_rest_of_line ();
if (flag_mri)
mri_comment_end (stop, stopc);
return;
}
#ifdef md_cons_align
md_cons_align (nbytes);
#endif
c = 0;
do
{
#ifdef TC_M68K
if (flag_m68k_mri)
parse_mri_cons (&exp, (unsigned int) nbytes);
else
#endif
TC_PARSE_CONS_EXPRESSION (&exp, (unsigned int) nbytes);
if (rva)
{
if (exp.X_op == O_symbol)
exp.X_op = O_symbol_rva;
else
as_fatal (_("rva without symbol"));
}
emit_expr (&exp, (unsigned int) nbytes);
++c;
}
while (*input_line_pointer++ == ',');
if (flag_mri && nbytes == 1 && (c & 1) != 0)
mri_pending_align = 1;
input_line_pointer--;
demand_empty_rest_of_line ();
if (flag_mri)
mri_comment_end (stop, stopc);
}
void
cons (int size)
{
cons_worker (size, 0);
}
void
s_rva (int size)
{
cons_worker (size, 1);
}
void
emit_expr (expressionS *exp, unsigned int nbytes)
{
operatorT op;
register char *p;
valueT extra_digit = 0;
if (need_pass_2)
return;
dot_value = frag_now_fix ();
#ifndef NO_LISTING
#ifdef OBJ_ELF
{
static int dwarf_line = -1;
if (strcmp (segment_name (now_seg), ".line") != 0)
dwarf_line = -1;
else if (dwarf_line >= 0
&& nbytes == 2
&& exp->X_op == O_constant
&& (exp->X_add_number == -1 || exp->X_add_number == 0xffff))
listing_source_line ((unsigned int) dwarf_line);
else if (nbytes == 4
&& exp->X_op == O_constant
&& exp->X_add_number >= 0)
dwarf_line = exp->X_add_number;
else
dwarf_line = -1;
}
{
static int dwarf_file = 0;
if (strcmp (segment_name (now_seg), ".debug") != 0)
dwarf_file = 0;
else if (dwarf_file == 0
&& nbytes == 2
&& exp->X_op == O_constant
&& exp->X_add_number == 0x11)
dwarf_file = 1;
else if (dwarf_file == 1
&& nbytes == 2
&& exp->X_op == O_constant
&& exp->X_add_number == 0x12)
dwarf_file = 2;
else if (dwarf_file == 2
&& nbytes == 4)
dwarf_file = 3;
else if (dwarf_file == 3
&& nbytes == 2
&& exp->X_op == O_constant
&& exp->X_add_number == 0x38)
dwarf_file = 4;
else
dwarf_file = 0;
if (dwarf_file == 4)
dwarf_file_string = 1;
else
dwarf_file_string = 0;
}
#endif
#endif
if (check_eh_frame (exp, &nbytes))
return;
op = exp->X_op;
if (now_seg == absolute_section)
{
if (op != O_constant || exp->X_add_number != 0)
as_bad (_("attempt to store value in absolute section"));
abs_section_offset += nbytes;
return;
}
if (op == O_uminus
&& exp->X_add_number == 0
&& symbol_get_value_expression (exp->X_add_symbol)->X_op == O_big
&& symbol_get_value_expression (exp->X_add_symbol)->X_add_number > 0)
{
int i;
unsigned long carry;
exp = symbol_get_value_expression (exp->X_add_symbol);
carry = 1;
for (i = 0; i < exp->X_add_number; i++)
{
unsigned long next;
next = (((~(generic_bignum[i] & LITTLENUM_MASK))
& LITTLENUM_MASK)
+ carry);
generic_bignum[i] = next & LITTLENUM_MASK;
carry = next >> LITTLENUM_NUMBER_OF_BITS;
}
extra_digit = (valueT) -1;
op = O_big;
}
if (op == O_absent || op == O_illegal)
{
as_warn (_("zero assumed for missing expression"));
exp->X_add_number = 0;
op = O_constant;
}
else if (op == O_big && exp->X_add_number <= 0)
{
as_bad (_("floating point number invalid"));
exp->X_add_number = 0;
op = O_constant;
}
else if (op == O_register)
{
as_warn (_("register value used as expression"));
op = O_constant;
}
p = frag_more ((int) nbytes);
#ifndef WORKING_DOT_WORD
if (op == O_subtract && nbytes == 2)
{
struct broken_word *x;
x = (struct broken_word *) xmalloc (sizeof (struct broken_word));
x->next_broken_word = broken_words;
broken_words = x;
x->seg = now_seg;
x->subseg = now_subseg;
x->frag = frag_now;
x->word_goes_here = p;
x->dispfrag = 0;
x->add = exp->X_add_symbol;
x->sub = exp->X_op_symbol;
x->addnum = exp->X_add_number;
x->added = 0;
x->use_jump = 0;
new_broken_words++;
return;
}
#endif
if (op == O_constant && nbytes > sizeof (valueT))
{
valueT val;
int gencnt;
if (!exp->X_unsigned && exp->X_add_number < 0)
extra_digit = (valueT) -1;
val = (valueT) exp->X_add_number;
gencnt = 0;
do
{
generic_bignum[gencnt] = val & LITTLENUM_MASK;
val >>= LITTLENUM_NUMBER_OF_BITS;
++gencnt;
}
while (val != 0);
op = exp->X_op = O_big;
exp->X_add_number = gencnt;
}
if (op == O_constant)
{
register valueT get;
register valueT use;
register valueT mask;
valueT hibit;
register valueT unmask;
if (nbytes >= sizeof (valueT))
{
mask = 0;
if (nbytes > sizeof (valueT))
hibit = 0;
else
hibit = (valueT) 1 << (nbytes * BITS_PER_CHAR - 1);
}
else
{
mask = ~(valueT) 0 << (BITS_PER_CHAR * nbytes);
hibit = (valueT) 1 << (nbytes * BITS_PER_CHAR - 1);
}
unmask = ~mask;
#ifdef NEVER
"Do this mod if you want every overflow check to assume SIGNED 2's complement data.";
mask = ~(unmask >> 1);
#endif
get = exp->X_add_number;
use = get & unmask;
if ((get & mask) != 0
&& ((get & mask) != mask
|| (get & hibit) == 0))
{
as_warn (_("value 0x%lx truncated to 0x%lx"),
(unsigned long) get, (unsigned long) use);
}
md_number_to_chars (p, use, (int) nbytes);
}
else if (op == O_big)
{
unsigned int size;
LITTLENUM_TYPE *nums;
know (nbytes % CHARS_PER_LITTLENUM == 0);
size = exp->X_add_number * CHARS_PER_LITTLENUM;
if (nbytes < size)
{
as_warn (_("bignum truncated to %d bytes"), nbytes);
size = nbytes;
}
if (target_big_endian)
{
while (nbytes > size)
{
md_number_to_chars (p, extra_digit, CHARS_PER_LITTLENUM);
nbytes -= CHARS_PER_LITTLENUM;
p += CHARS_PER_LITTLENUM;
}
nums = generic_bignum + size / CHARS_PER_LITTLENUM;
while (size >= CHARS_PER_LITTLENUM)
{
--nums;
md_number_to_chars (p, (valueT) *nums, CHARS_PER_LITTLENUM);
size -= CHARS_PER_LITTLENUM;
p += CHARS_PER_LITTLENUM;
}
}
else
{
nums = generic_bignum;
while (size >= CHARS_PER_LITTLENUM)
{
md_number_to_chars (p, (valueT) *nums, CHARS_PER_LITTLENUM);
++nums;
size -= CHARS_PER_LITTLENUM;
p += CHARS_PER_LITTLENUM;
nbytes -= CHARS_PER_LITTLENUM;
}
while (nbytes >= CHARS_PER_LITTLENUM)
{
md_number_to_chars (p, extra_digit, CHARS_PER_LITTLENUM);
nbytes -= CHARS_PER_LITTLENUM;
p += CHARS_PER_LITTLENUM;
}
}
}
else
{
memset (p, 0, nbytes);
#ifdef BFD_ASSEMBLER
#ifdef TC_CONS_FIX_NEW
TC_CONS_FIX_NEW (frag_now, p - frag_now->fr_literal, nbytes, exp);
#else
{
bfd_reloc_code_real_type r;
switch (nbytes)
{
case 1:
r = BFD_RELOC_8;
break;
case 2:
r = BFD_RELOC_16;
break;
case 4:
r = BFD_RELOC_32;
break;
case 8:
r = BFD_RELOC_64;
break;
default:
as_bad (_("unsupported BFD relocation size %u"), nbytes);
r = BFD_RELOC_32;
break;
}
fix_new_exp (frag_now, p - frag_now->fr_literal, (int) nbytes, exp,
0, r);
}
#endif
#else
#ifdef TC_CONS_FIX_NEW
TC_CONS_FIX_NEW (frag_now, p - frag_now->fr_literal, nbytes, exp);
#else
#ifndef TC_CONS_RELOC
#ifdef NO_RELOC
#define TC_CONS_RELOC NO_RELOC
#else
#define TC_CONS_RELOC 0
#endif
#endif
fix_new_exp (frag_now, p - frag_now->fr_literal, (int) nbytes, exp, 0,
TC_CONS_RELOC);
#endif
#endif
}
}
#ifdef BITFIELD_CONS_EXPRESSIONS
static void
parse_bitfield_cons (exp, nbytes)
expressionS *exp;
unsigned int nbytes;
{
unsigned int bits_available = BITS_PER_CHAR * nbytes;
char *hold = input_line_pointer;
(void) expression (exp);
if (*input_line_pointer == ':')
{
long value = 0;
for (;;)
{
unsigned long width;
if (*input_line_pointer != ':')
{
input_line_pointer = hold;
break;
}
if (exp->X_op == O_absent)
{
as_warn (_("using a bit field width of zero"));
exp->X_add_number = 0;
exp->X_op = O_constant;
}
if (exp->X_op != O_constant)
{
*input_line_pointer = '\0';
as_bad (_("field width \"%s\" too complex for a bitfield"), hold);
*input_line_pointer = ':';
demand_empty_rest_of_line ();
return;
}
if ((width = exp->X_add_number) > (BITS_PER_CHAR * nbytes))
{
as_warn (_("field width %lu too big to fit in %d bytes: truncated to %d bits"),
width, nbytes, (BITS_PER_CHAR * nbytes));
width = BITS_PER_CHAR * nbytes;
}
if (width > bits_available)
{
input_line_pointer = hold;
exp->X_add_number = value;
break;
}
hold = ++input_line_pointer;
(void) expression (exp);
if (exp->X_op != O_constant)
{
char cache = *input_line_pointer;
*input_line_pointer = '\0';
as_bad (_("field value \"%s\" too complex for a bitfield"), hold);
*input_line_pointer = cache;
demand_empty_rest_of_line ();
return;
}
value |= ((~(-1 << width) & exp->X_add_number)
<< ((BITS_PER_CHAR * nbytes) - bits_available));
if ((bits_available -= width) == 0
|| is_it_end_of_statement ()
|| *input_line_pointer != ',')
{
break;
}
hold = ++input_line_pointer;
(void) expression (exp);
}
exp->X_add_number = value;
exp->X_op = O_constant;
exp->X_unsigned = 1;
}
}
#endif
#ifdef TC_M68K
static void
parse_mri_cons (exp, nbytes)
expressionS *exp;
unsigned int nbytes;
{
if (*input_line_pointer != '\''
&& (input_line_pointer[1] != '\''
|| (*input_line_pointer != 'A'
&& *input_line_pointer != 'E')))
TC_PARSE_CONS_EXPRESSION (exp, nbytes);
else
{
unsigned int scan;
unsigned int result = 0;
if (*input_line_pointer == 'A')
++input_line_pointer;
else if (*input_line_pointer == 'E')
{
as_bad (_("EBCDIC constants are not supported"));
++input_line_pointer;
}
input_line_pointer++;
for (scan = 0; scan < nbytes; scan++)
{
if (*input_line_pointer == '\'')
{
if (input_line_pointer[1] == '\'')
{
input_line_pointer++;
}
else
break;
}
result = (result << 8) | (*input_line_pointer++);
}
while (scan < nbytes)
{
result <<= 8;
scan++;
}
exp->X_op = O_constant;
exp->X_add_number = result;
if (input_line_pointer[0] != '\'' ||
(input_line_pointer[0] == '\'' && input_line_pointer[1] == '\''))
{
input_line_pointer -= 2;
input_line_pointer[0] = ',';
input_line_pointer[1] = '\'';
}
else
input_line_pointer++;
}
}
#endif
#ifdef REPEAT_CONS_EXPRESSIONS
static void
parse_repeat_cons (exp, nbytes)
expressionS *exp;
unsigned int nbytes;
{
expressionS count;
register int i;
expression (exp);
if (*input_line_pointer != ':')
{
return;
}
++input_line_pointer;
expression (&count);
if (count.X_op != O_constant
|| count.X_add_number <= 0)
{
as_warn (_("unresolvable or nonpositive repeat count; using 1"));
return;
}
for (i = count.X_add_number - 1; i > 0; i--)
emit_expr (exp, nbytes);
}
#endif
static int
hex_float (int float_type, char *bytes)
{
int length;
int i;
switch (float_type)
{
case 'f':
case 'F':
case 's':
case 'S':
length = 4;
break;
case 'd':
case 'D':
case 'r':
case 'R':
length = 8;
break;
case 'x':
case 'X':
length = 12;
break;
case 'p':
case 'P':
length = 12;
break;
default:
as_bad (_("unknown floating type type '%c'"), float_type);
return -1;
}
i = 0;
while (hex_p (*input_line_pointer) || *input_line_pointer == '_')
{
int d;
if (*input_line_pointer == '_')
{
++input_line_pointer;
continue;
}
if (i >= length)
{
as_warn (_("floating point constant too large"));
return -1;
}
d = hex_value (*input_line_pointer) << 4;
++input_line_pointer;
while (*input_line_pointer == '_')
++input_line_pointer;
if (hex_p (*input_line_pointer))
{
d += hex_value (*input_line_pointer);
++input_line_pointer;
}
if (target_big_endian)
bytes[i] = d;
else
bytes[length - i - 1] = d;
++i;
}
if (i < length)
{
if (target_big_endian)
memset (bytes + i, 0, length - i);
else
memset (bytes, 0, length - i);
}
return length;
}
void
float_cons (
register int float_type )
{
register char *p;
int length;
register char *err;
char temp[MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT];
if (is_it_end_of_statement ())
{
demand_empty_rest_of_line ();
return;
}
#ifdef md_flush_pending_output
md_flush_pending_output ();
#endif
do
{
SKIP_WHITESPACE ();
if (input_line_pointer[0] == '0'
&& ISALPHA (input_line_pointer[1]))
input_line_pointer += 2;
if (input_line_pointer[0] == ':')
{
++input_line_pointer;
length = hex_float (float_type, temp);
if (length < 0)
{
ignore_rest_of_line ();
return;
}
}
else
{
err = md_atof (float_type, temp, &length);
know (length <= MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT);
know (length > 0);
if (err)
{
as_bad (_("bad floating literal: %s"), err);
ignore_rest_of_line ();
return;
}
}
if (!need_pass_2)
{
int count;
count = 1;
#ifdef REPEAT_CONS_EXPRESSIONS
if (*input_line_pointer == ':')
{
expressionS count_exp;
++input_line_pointer;
expression (&count_exp);
if (count_exp.X_op != O_constant
|| count_exp.X_add_number <= 0)
as_warn (_("unresolvable or nonpositive repeat count; using 1"));
else
count = count_exp.X_add_number;
}
#endif
while (--count >= 0)
{
p = frag_more (length);
memcpy (p, temp, (unsigned int) length);
}
}
SKIP_WHITESPACE ();
}
while (*input_line_pointer++ == ',');
--input_line_pointer;
demand_empty_rest_of_line ();
}
static inline int
sizeof_sleb128 (offsetT value)
{
register int size = 0;
register unsigned byte;
do
{
byte = (value & 0x7f);
value = (value >> 7) | ~(-(offsetT)1 >> 7);
size += 1;
}
while (!(((value == 0) && ((byte & 0x40) == 0))
|| ((value == -1) && ((byte & 0x40) != 0))));
return size;
}
static inline int
sizeof_uleb128 (valueT value)
{
register int size = 0;
register unsigned byte;
do
{
byte = (value & 0x7f);
value >>= 7;
size += 1;
}
while (value != 0);
return size;
}
int
sizeof_leb128 (valueT value, int sign)
{
if (sign)
return sizeof_sleb128 ((offsetT) value);
else
return sizeof_uleb128 (value);
}
static inline int
output_sleb128 (char *p, offsetT value)
{
register char *orig = p;
register int more;
do
{
unsigned byte = (value & 0x7f);
value = (value >> 7) | ~(-(offsetT)1 >> 7);
more = !((((value == 0) && ((byte & 0x40) == 0))
|| ((value == -1) && ((byte & 0x40) != 0))));
if (more)
byte |= 0x80;
*p++ = byte;
}
while (more);
return p - orig;
}
static inline int
output_uleb128 (char *p, valueT value)
{
char *orig = p;
do
{
unsigned byte = (value & 0x7f);
value >>= 7;
if (value != 0)
byte |= 0x80;
*p++ = byte;
}
while (value != 0);
return p - orig;
}
int
output_leb128 (char *p, valueT value, int sign)
{
if (sign)
return output_sleb128 (p, (offsetT) value);
else
return output_uleb128 (p, value);
}
static inline int
output_big_sleb128 (char *p, LITTLENUM_TYPE *bignum, int size)
{
char *orig = p;
valueT val = 0;
int loaded = 0;
unsigned byte;
while (size > 0 && bignum[size - 1] == (LITTLENUM_TYPE) -1)
size--;
do
{
if (loaded < 7 && size > 0)
{
val |= (*bignum << loaded);
loaded += 8 * CHARS_PER_LITTLENUM;
size--;
bignum++;
}
byte = val & 0x7f;
loaded -= 7;
val >>= 7;
if (size == 0)
{
if ((val == 0 && (byte & 0x40) == 0)
|| (~(val | ~(((valueT) 1 << loaded) - 1)) == 0
&& (byte & 0x40) != 0))
byte |= 0x80;
}
if (orig)
*p = byte;
p++;
}
while (byte & 0x80);
return p - orig;
}
static inline int
output_big_uleb128 (char *p, LITTLENUM_TYPE *bignum, int size)
{
char *orig = p;
valueT val = 0;
int loaded = 0;
unsigned byte;
while (size > 0 && bignum[size - 1] == 0)
size--;
do
{
if (loaded < 7 && size > 0)
{
val |= (*bignum << loaded);
loaded += 8 * CHARS_PER_LITTLENUM;
size--;
bignum++;
}
byte = val & 0x7f;
loaded -= 7;
val >>= 7;
if (size > 0 || val)
byte |= 0x80;
if (orig)
*p = byte;
p++;
}
while (byte & 0x80);
return p - orig;
}
static int
output_big_leb128 (char *p, LITTLENUM_TYPE *bignum, int size, int sign)
{
if (sign)
return output_big_sleb128 (p, bignum, size);
else
return output_big_uleb128 (p, bignum, size);
}
void
emit_leb128_expr (expressionS *exp, int sign)
{
operatorT op = exp->X_op;
int nbytes;
if (op == O_absent || op == O_illegal)
{
as_warn (_("zero assumed for missing expression"));
exp->X_add_number = 0;
op = O_constant;
}
else if (op == O_big && exp->X_add_number <= 0)
{
as_bad (_("floating point number invalid"));
exp->X_add_number = 0;
op = O_constant;
}
else if (op == O_register)
{
as_warn (_("register value used as expression"));
op = O_constant;
}
nbytes = -1;
if (check_eh_frame (exp, &nbytes))
abort ();
#ifdef md_cons_align
md_cons_align (1);
#endif
if (op == O_constant)
{
valueT value = exp->X_add_number;
int size;
char *p;
size = sizeof_leb128 (value, sign);
p = frag_more (size);
output_leb128 (p, value, sign);
}
else if (op == O_big)
{
int size;
char *p;
size = output_big_leb128 (NULL, generic_bignum, exp->X_add_number, sign);
p = frag_more (size);
output_big_leb128 (p, generic_bignum, exp->X_add_number, sign);
}
else
{
frag_var (rs_leb128, sizeof_uleb128 (~(valueT) 0), 0, sign,
make_expr_symbol (exp), 0, (char *) NULL);
}
}
void
s_leb128 (int sign)
{
expressionS exp;
#ifdef md_flush_pending_output
md_flush_pending_output ();
#endif
do
{
expression (&exp);
emit_leb128_expr (&exp, sign);
}
while (*input_line_pointer++ == ',');
input_line_pointer--;
demand_empty_rest_of_line ();
}
void
stringer (
register int append_zero )
{
register unsigned int c;
char *start;
#ifdef md_flush_pending_output
md_flush_pending_output ();
#endif
if (is_it_end_of_statement ())
{
c = 0;
++input_line_pointer;
}
else
{
c = ',';
}
if (now_seg == absolute_section)
{
as_bad (_("strings must be placed into a section"));
c = 0;
ignore_rest_of_line ();
}
while (c == ',' || c == '<' || c == '"')
{
SKIP_WHITESPACE ();
switch (*input_line_pointer)
{
case '\"':
++input_line_pointer;
start = input_line_pointer;
while (is_a_char (c = next_char_of_string ()))
{
FRAG_APPEND_1_CHAR (c);
}
if (append_zero)
{
FRAG_APPEND_1_CHAR (0);
}
know (input_line_pointer[-1] == '\"');
#ifndef NO_LISTING
#ifdef OBJ_ELF
if (strcmp (segment_name (now_seg), ".debug") != 0)
dwarf_file_string = 0;
else if (dwarf_file_string)
{
c = input_line_pointer[-1];
input_line_pointer[-1] = '\0';
listing_source_file (start);
input_line_pointer[-1] = c;
}
#endif
#endif
break;
case '<':
input_line_pointer++;
c = get_single_number ();
FRAG_APPEND_1_CHAR (c);
if (*input_line_pointer != '>')
{
as_bad (_("expected <nn>"));
}
input_line_pointer++;
break;
case ',':
input_line_pointer++;
break;
}
SKIP_WHITESPACE ();
c = *input_line_pointer;
}
demand_empty_rest_of_line ();
}
unsigned int
next_char_of_string (void)
{
register unsigned int c;
c = *input_line_pointer++ & CHAR_MASK;
switch (c)
{
case '\"':
c = NOT_A_CHAR;
break;
case '\n':
as_warn (_("unterminated string; newline inserted"));
bump_line_counters ();
break;
#ifndef NO_STRING_ESCAPES
case '\\':
switch (c = *input_line_pointer++)
{
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 'v':
c = '\013';
break;
case '\\':
case '"':
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
{
long number;
int i;
for (i = 0, number = 0;
ISDIGIT (c) && i < 3;
c = *input_line_pointer++, i++)
{
number = number * 8 + c - '0';
}
c = number & 0xff;
}
--input_line_pointer;
break;
case 'x':
case 'X':
{
long number;
number = 0;
c = *input_line_pointer++;
while (ISXDIGIT (c))
{
if (ISDIGIT (c))
number = number * 16 + c - '0';
else if (ISUPPER (c))
number = number * 16 + c - 'A' + 10;
else
number = number * 16 + c - 'a' + 10;
c = *input_line_pointer++;
}
c = number & 0xff;
--input_line_pointer;
}
break;
case '\n':
as_warn (_("unterminated string; newline inserted"));
c = '\n';
bump_line_counters ();
break;
default:
#ifdef ONLY_STANDARD_ESCAPES
as_bad (_("bad escaped character in string"));
c = '?';
#endif
break;
}
break;
#endif
default:
break;
}
return (c);
}
static segT
get_segmented_expression (register expressionS *expP)
{
register segT retval;
retval = expression (expP);
if (expP->X_op == O_illegal
|| expP->X_op == O_absent
|| expP->X_op == O_big)
{
as_bad (_("expected address expression"));
expP->X_op = O_constant;
expP->X_add_number = 0;
retval = absolute_section;
}
return retval;
}
static segT
get_known_segmented_expression (register expressionS *expP)
{
register segT retval;
if ((retval = get_segmented_expression (expP)) == undefined_section)
{
if (expP->X_add_symbol != NULL
&& S_GET_SEGMENT (expP->X_add_symbol) != expr_section)
as_warn (_("symbol \"%s\" undefined; zero assumed"),
S_GET_NAME (expP->X_add_symbol));
else
as_warn (_("some symbol undefined; zero assumed"));
retval = absolute_section;
expP->X_op = O_constant;
expP->X_add_number = 0;
}
know (retval == absolute_section || SEG_NORMAL (retval));
return (retval);
}
offsetT
get_absolute_expr (expressionS *exp)
{
expression (exp);
if (exp->X_op != O_constant)
{
if (exp->X_op != O_absent)
as_bad (_("bad or irreducible absolute expression"));
exp->X_add_number = 0;
}
return exp->X_add_number;
}
offsetT
get_absolute_expression (void)
{
expressionS exp;
return get_absolute_expr (&exp);
}
char
get_absolute_expression_and_terminator (long *val_pointer )
{
*val_pointer = (long) get_absolute_expression ();
return (*input_line_pointer++);
}
char *
demand_copy_C_string (int *len_pointer)
{
register char *s;
if ((s = demand_copy_string (len_pointer)) != 0)
{
register int len;
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;
}
char *
demand_copy_string (int *lenP)
{
register unsigned int c;
register int len;
char *retval;
len = 0;
SKIP_WHITESPACE ();
if (*input_line_pointer == '\"')
{
input_line_pointer++;
while (is_a_char (c = next_char_of_string ()))
{
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);
}
int
is_it_end_of_statement (void)
{
SKIP_WHITESPACE ();
return (is_end_of_line[(unsigned char) *input_line_pointer]);
}
void
equals (char *sym_name, int reassign)
{
register symbolS *symbolP;
char *stop = NULL;
char stopc;
input_line_pointer++;
if (*input_line_pointer == '=')
input_line_pointer++;
while (*input_line_pointer == ' ' || *input_line_pointer == '\t')
input_line_pointer++;
if (flag_mri)
stop = mri_comment_field (&stopc);
if (sym_name[0] == '.' && sym_name[1] == '\0')
{
register segT segment;
expressionS exp;
segment = get_known_segmented_expression (&exp);
if (!need_pass_2)
do_org (segment, &exp, 0);
}
else
{
#ifdef OBJ_COFF
int local;
symbolP = symbol_find (sym_name);
local = symbolP == NULL;
if (local)
#endif
symbolP = symbol_find_or_make (sym_name);
if (!reassign
&& S_IS_DEFINED (symbolP)
&& S_GET_SEGMENT (symbolP) != reg_section)
as_bad (_("symbol `%s' is already defined"), S_GET_NAME (symbolP));
#ifdef OBJ_COFF
if (local)
SF_SET_LOCAL (symbolP);
#endif
pseudo_set (symbolP);
}
if (flag_mri)
{
demand_empty_rest_of_line ();
mri_comment_end (stop, stopc);
}
}
void
s_incbin (int x ATTRIBUTE_UNUSED)
{
FILE * binfile;
char * path;
char * filename;
char * binfrag;
long skip = 0;
long count = 0;
long bytes;
int len;
#ifdef md_flush_pending_output
md_flush_pending_output ();
#endif
SKIP_WHITESPACE ();
filename = demand_copy_string (& len);
if (filename == NULL)
return;
SKIP_WHITESPACE ();
if (* input_line_pointer == ',')
{
++ input_line_pointer;
skip = get_absolute_expression ();
SKIP_WHITESPACE ();
if (* input_line_pointer == ',')
{
++ input_line_pointer;
count = get_absolute_expression ();
if (count == 0)
as_warn (_(".incbin count zero, ignoring `%s'"), filename);
SKIP_WHITESPACE ();
}
}
demand_empty_rest_of_line ();
binfile = fopen (filename, FOPEN_RB);
if (binfile == NULL)
{
int i;
path = xmalloc ((unsigned long) len + include_dir_maxlen + 5);
for (i = 0; i < include_dir_count; i++)
{
sprintf (path, "%s/%s", include_dirs[i], filename);
binfile = fopen (path, FOPEN_RB);
if (binfile != NULL)
break;
}
if (binfile == NULL)
as_bad (_("file not found: %s"), filename);
}
else
path = xstrdup (filename);
if (binfile)
{
long file_len;
register_dependency (path);
if (fseek (binfile, 0, SEEK_END) != 0)
{
as_bad (_("seek to end of .incbin file failed `%s'"), path);
goto done;
}
file_len = ftell (binfile);
if (count == 0)
count = file_len;
if (skip + count > file_len)
{
as_bad (_("skip (%ld) + count (%ld) larger than file size (%ld)"),
skip, count, file_len);
goto done;
}
if (fseek (binfile, skip, SEEK_SET) != 0)
{
as_bad (_("could not skip to %ld in file `%s'"), skip, path);
goto done;
}
binfrag = frag_more (count);
bytes = fread (binfrag, 1, count, binfile);
if (bytes < count)
as_warn (_("truncated file `%s', %ld of %ld bytes read"),
path, bytes, count);
}
done:
if (binfile != NULL)
fclose (binfile);
if (path)
free (path);
}
void
s_include (int arg ATTRIBUTE_UNUSED)
{
char *filename;
int i;
FILE *try;
char *path;
if (!flag_m68k_mri)
{
filename = demand_copy_string (&i);
if (filename == NULL)
{
return;
}
}
else
{
SKIP_WHITESPACE ();
i = 0;
while (!is_end_of_line[(unsigned char) *input_line_pointer]
&& *input_line_pointer != ' '
&& *input_line_pointer != '\t')
{
obstack_1grow (¬es, *input_line_pointer);
++input_line_pointer;
++i;
}
obstack_1grow (¬es, '\0');
filename = obstack_finish (¬es);
while (!is_end_of_line[(unsigned char) *input_line_pointer])
++input_line_pointer;
}
demand_empty_rest_of_line ();
path = xmalloc ((unsigned long) i + include_dir_maxlen + 5 );
for (i = 0; i < include_dir_count; i++)
{
strcpy (path, include_dirs[i]);
strcat (path, "/");
strcat (path, filename);
if (0 != (try = fopen (path, FOPEN_RT)))
{
fclose (try);
goto gotit;
}
}
free (path);
path = filename;
gotit:
register_dependency (path);
input_scrub_insert_file (path);
}
void
add_include_dir (char *path)
{
int i;
if (include_dir_count == 0)
{
include_dirs = (char **) xmalloc (2 * sizeof (*include_dirs));
include_dirs[0] = ".";
include_dir_count = 2;
}
else
{
include_dir_count++;
include_dirs =
(char **) realloc (include_dirs,
include_dir_count * sizeof (*include_dirs));
}
include_dirs[include_dir_count - 1] = path;
i = strlen (path);
if (i > include_dir_maxlen)
include_dir_maxlen = i;
}
static void
generate_file_debug (void)
{
if (debug_type == DEBUG_STABS)
stabs_generate_asm_file ();
}
void
generate_lineno_debug (void)
{
switch (debug_type)
{
case DEBUG_UNSPECIFIED:
case DEBUG_NONE:
case DEBUG_DWARF:
break;
case DEBUG_STABS:
stabs_generate_asm_lineno ();
break;
case DEBUG_ECOFF:
ecoff_generate_asm_lineno ();
break;
case DEBUG_DWARF2:
break;
}
}
void
s_func (int end_p)
{
do_s_func (end_p, NULL);
}
void
do_s_func (int end_p, const char *default_prefix)
{
static char *current_name;
static char *current_label;
if (end_p)
{
if (current_name == NULL)
{
as_bad (_("missing .func"));
ignore_rest_of_line ();
return;
}
if (debug_type == DEBUG_STABS)
stabs_generate_asm_endfunc (current_name, current_label);
current_name = current_label = NULL;
}
else
{
char *name, *label;
char delim1, delim2;
if (current_name != NULL)
{
as_bad (_(".endfunc missing for previous .func"));
ignore_rest_of_line ();
return;
}
name = input_line_pointer;
delim1 = get_symbol_end ();
name = xstrdup (name);
*input_line_pointer = delim1;
SKIP_WHITESPACE ();
if (*input_line_pointer != ',')
{
if (default_prefix)
asprintf (&label, "%s%s", default_prefix, name);
else
{
char leading_char = 0;
#ifdef BFD_ASSEMBLER
leading_char = bfd_get_symbol_leading_char (stdoutput);
#endif
if (leading_char)
asprintf (&label, "%c%s", leading_char, name);
else
label = name;
}
}
else
{
++input_line_pointer;
SKIP_WHITESPACE ();
label = input_line_pointer;
delim2 = get_symbol_end ();
label = xstrdup (label);
*input_line_pointer = delim2;
}
if (debug_type == DEBUG_STABS)
stabs_generate_asm_func (name, label);
current_name = name;
current_label = label;
}
demand_empty_rest_of_line ();
}
void
s_ignore (int arg ATTRIBUTE_UNUSED)
{
while (!is_end_of_line[(unsigned char) *input_line_pointer])
{
++input_line_pointer;
}
++input_line_pointer;
}
void
read_print_statistics (FILE *file)
{
hash_print_statistics (file, "pseudo-op table", po_hash);
}
void
input_scrub_insert_line (const char *line)
{
sb newline;
sb_new (&newline);
sb_add_string (&newline, line);
input_scrub_include_sb (&newline, input_line_pointer, 0);
sb_kill (&newline);
buffer_limit = input_scrub_next_buffer (&input_line_pointer);
}
void
input_scrub_insert_file (char *path)
{
input_scrub_include_file (path, input_line_pointer);
buffer_limit = input_scrub_next_buffer (&input_line_pointer);
}