aboutsummaryrefslogtreecommitdiff
path: root/gas/read.c
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@airs.com>1995-08-21 18:35:11 +0000
committerIan Lance Taylor <ian@airs.com>1995-08-21 18:35:11 +0000
commit7e047ac2c1fcb16f721c715a48c8d4b8b4776485 (patch)
treee564914df3cf5fa253fbf65ea8b9b36deaddd40a /gas/read.c
parent7172e2266f4a25fc34dda564ac13c89c9d855cde (diff)
downloadgdb-7e047ac2c1fcb16f721c715a48c8d4b8b4776485.zip
gdb-7e047ac2c1fcb16f721c715a48c8d4b8b4776485.tar.gz
gdb-7e047ac2c1fcb16f721c715a48c8d4b8b4776485.tar.bz2
Add support for macros.
* as.c: Include sb.h and macro.h. (max_macro_next): New global variable. (main): Call macro_init. (macro_expr): New static function. * as.h (max_macro_nest): Declare. * read.c (line_label): Rename from mri_line_label. Change all uses. (potable): Add exitm, irp, irpc, macro, mexit, rept. (read_a_source_file): Always clear line_label at the start of a line, not just when flag_mri or LABELS_WITHOUT_COLONS. Fixup MRI/LABELS_WITHOUT_COLONS handling. In MRI mode, permit label: equ val. Set line_label when calling colon. In MRI mode, a leading '.' does not imply a pseudo-op. Check for macro expansion before calling md_assemble. (s_irp): New function. (get_line_sb): New static function. (s_macro): New function. (s_mexit): New function. (s_rept): New function. * read.h (line_label): Rename from mri_line_label. (s_irp, s_rept): Declare. (s_macro, s_mexit): Declare. * input-scrub.c: Include sb.h. (sb_index, from_sb): New static variables. (macro_nest): New static variable. (struct input_save): Add sb_index and from_sb fields. Change next_saved_file field to be struct input_save *. (next_saved_file): Changed to be struct input_save *. (input_scrub_push): Change to return type struct input_save *. Save sb_index and from_sb. (input_scrub_pop): Change parameter type to struct input_save *. Restore sb_index and from_sb. (input_scrub_include_sb): New function. (input_scrub_next_buffer): Handle reading from from_sb. (bump_line_counters): Only increment lines if not using from_sb. * config/tc-m68k.c (opt_table): Add nest. (opt_nest): New static function. * gasp.c: Include sb.h and macro.h. Move all sb related functions and definitions to sb.h and sb.c. Move all macro related functions and definitions to macro.h and macro.c. * sb.h, sb.c: New files, extracted from gasp.c. * macro.h, macro.c: Likewise. * Makefile.in (OBJS): Add sb.o and macro.o (GASPOBJS): Define. (gasp.new): Depend upon $(GASPOBJS). Use $(GASPOBJS) to link. (TARG_CPU_DEP_m68k): Depend upon subsegs.h. (gasp.o): Depend upon sb.h and macro.h. (sb.o): New target. (macro.o): New target. (as.o): Depend upon sb.h and macro.h. (input-scrub.o): Depend upon sb.h. (read.o): Depend upon sb.h and macro.h.
Diffstat (limited to 'gas/read.c')
-rw-r--r--gas/read.c258
1 files changed, 226 insertions, 32 deletions
diff --git a/gas/read.c b/gas/read.c
index 7a9cd3e..a117b75 100644
--- a/gas/read.c
+++ b/gas/read.c
@@ -42,6 +42,8 @@ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307
#include "as.h"
#include "subsegs.h"
+#include "sb.h"
+#include "macro.h"
#include "libiberty.h"
#include "obstack.h"
#include "listing.h"
@@ -176,7 +178,7 @@ addressT abs_section_offset;
/* If this line had an MRI style label, it is stored in this variable.
This is used by some of the MRI pseudo-ops. */
-symbolS *mri_line_label;
+symbolS *line_label;
/* This global variable is used to support MRI common sections. We
translate such sections into a common symbol. This variable is
@@ -197,6 +199,7 @@ int is_it_end_of_statement PARAMS ((void));
static segT get_segmented_expression PARAMS ((expressionS *expP));
static segT get_known_segmented_expression PARAMS ((expressionS * expP));
static void pobegin PARAMS ((void));
+static int get_line_sb PARAMS ((sb *));
void
@@ -275,6 +278,7 @@ static const pseudo_typeS potable[] =
/* endef */
{"equ", s_set, 0},
/* err */
+ {"exitm", s_mexit, 0},
/* extend */
{"extern", s_ignore, 0}, /* We treat all undef as ext */
{"appfile", s_app_file, 1},
@@ -288,6 +292,7 @@ static const pseudo_typeS potable[] =
{"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},
@@ -295,18 +300,23 @@ static const pseudo_typeS potable[] =
{"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},
{"include", s_include, 0},
{"int", cons, 4},
+ {"irp", s_irp, 0},
+ {"irpc", s_irp, 1},
{"lcomm", s_lcomm, 0},
{"lflags", listing_flags, 0}, /* Listing flags */
{"list", listing_list, 1}, /* Turn listing on */
{"llen", listing_psize, 1},
{"long", cons, 4},
{"lsym", s_lsym, 0},
+ {"macro", s_macro, 0},
+ {"mexit", s_mexit, 0},
{"noformat", s_ignore, 0},
{"nolist", listing_list, 0}, /* Turn listing off */
{"nopage", listing_nopage, 0},
@@ -319,6 +329,7 @@ static const pseudo_typeS potable[] =
{"psize", listing_psize, 0}, /* set paper size */
/* print */
{"quad", cons, 8},
+ {"rept", s_rept, 0},
{"sbttl", listing_title, 1}, /* Subtitle of listing */
/* scl */
/* sect */
@@ -457,43 +468,47 @@ read_a_source_file (name)
if (input_line_pointer[-1] == '\n')
bump_line_counters ();
+ line_label = NULL;
+
if (flag_mri
#ifdef LABELS_WITHOUT_COLONS
|| 1
#endif
)
{
- mri_line_label = NULL;
-
/* Text at the start of a line must be a label, we
run down and stick a colon in. */
if (is_name_beginner (*input_line_pointer))
{
char *line_start = input_line_pointer;
- char c = get_symbol_end ();
+ char c;
+
+ HANDLE_CONDITIONAL_ASSEMBLY ();
- if (! ignore_input ())
+ c = get_symbol_end ();
+
+ /* In MRI mode, the EQU pseudoop must be
+ handled specially. */
+ if (flag_mri)
{
- /* In MRI mode, the EQU pseudoop must be
- handled specially. */
- if (flag_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'))
{
- if (((strncasecmp (input_line_pointer + 1,
- "EQU", 3) == 0)
- || (strncasecmp (input_line_pointer + 1,
- "SET", 3) == 0))
- && (input_line_pointer[4] == ' '
- || input_line_pointer[4] == '\t'))
- {
- input_line_pointer += 4;
- equals (line_start);
- continue;
- }
+ input_line_pointer = rest + 3;
+ equals (line_start);
+ continue;
}
-
- mri_line_label = colon (line_start);
}
+ line_label = colon (line_start);
+
*input_line_pointer = c;
if (c == ':')
input_line_pointer++;
@@ -544,7 +559,27 @@ read_a_source_file (name)
*/
if (TC_START_LABEL(c, input_line_pointer))
{
- colon (s); /* user-defined label */
+ if (flag_mri)
+ {
+ char *rest = input_line_pointer + 1;
+
+ /* In MRI mode, \tsym: set 0 is permitted. */
+
+ 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);
+ continue;
+ }
+ }
+
+ line_label = colon (s); /* user-defined label */
*input_line_pointer++ = ':'; /* Put ':' back for error messages' sake. */
/* Input_line_pointer->after ':'. */
SKIP_WHITESPACE ();
@@ -591,7 +626,8 @@ read_a_source_file (name)
pop = NULL;
}
- if (pop != NULL || *s == '.')
+ if (pop != NULL
+ || (! flag_mri && *s == '.'))
{
/*
* PSEUDO - OP.
@@ -684,6 +720,25 @@ read_a_source_file (name)
}
#endif
+ if (macro_defined)
+ {
+ sb out;
+ const char *err;
+
+ if (check_macro (s, &out, '\0', &err))
+ {
+ if (err != NULL)
+ as_bad (err);
+ *input_line_pointer++ = c;
+ input_scrub_include_sb (&out,
+ input_line_pointer);
+ sb_kill (&out);
+ buffer_limit =
+ input_scrub_next_buffer (&input_line_pointer);
+ continue;
+ }
+ }
+
md_assemble (s); /* Assemble 1 instruction. */
*input_line_pointer++ = c;
@@ -1076,12 +1131,12 @@ s_mri_common (small)
c = *input_line_pointer;
*input_line_pointer = '\0';
- if (mri_line_label != NULL)
+ if (line_label != NULL)
{
- alc = (char *) xmalloc (strlen (S_GET_NAME (mri_line_label))
+ alc = (char *) xmalloc (strlen (S_GET_NAME (line_label))
+ (input_line_pointer - name)
+ 1);
- sprintf (alc, "%s%s", name, S_GET_NAME (mri_line_label));
+ sprintf (alc, "%s%s", name, S_GET_NAME (line_label));
name = alc;
}
}
@@ -1119,13 +1174,13 @@ s_mri_common (small)
S_SET_ALIGN (sym, align);
#endif
- if (mri_line_label != NULL)
+ if (line_label != NULL)
{
- mri_line_label->sy_value.X_op = O_symbol;
- mri_line_label->sy_value.X_add_symbol = sym;
- mri_line_label->sy_value.X_add_number = S_GET_VALUE (sym);
- mri_line_label->sy_frag = &zero_address_frag;
- S_SET_SEGMENT (mri_line_label, expr_section);
+ line_label->sy_value.X_op = O_symbol;
+ line_label->sy_value.X_add_symbol = sym;
+ line_label->sy_value.X_add_number = S_GET_VALUE (sym);
+ line_label->sy_frag = &zero_address_frag;
+ S_SET_SEGMENT (line_label, expr_section);
}
/* FIXME: We just ignore the small argument, which distinguishes
@@ -1345,6 +1400,37 @@ s_globl (ignore)
demand_empty_rest_of_line ();
}
+/* Handle the MRI IRP and IRPC pseudo-ops. */
+
+void
+s_irp (irpc)
+ 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, '\0');
+ if (err != NULL)
+ as_bad_where (file, line, "%s", err);
+
+ sb_kill (&s);
+
+ input_scrub_include_sb (&out, input_line_pointer);
+ sb_kill (&out);
+ buffer_limit = input_scrub_next_buffer (&input_line_pointer);
+}
+
void
s_lcomm (needs_align)
/* 1 if this was a ".bss" directive, which may require a 3rd argument
@@ -1569,6 +1655,84 @@ s_lsym (ignore)
demand_empty_rest_of_line ();
} /* s_lsym() */
+/* Read a line into an sb. */
+
+static int
+get_line_sb (line)
+ sb *line;
+{
+ if (input_line_pointer >= buffer_limit)
+ {
+ buffer_limit = input_scrub_next_buffer (&input_line_pointer);
+ if (buffer_limit == 0)
+ return 0;
+ }
+
+ while (! is_end_of_line[(unsigned char) *input_line_pointer])
+ sb_add_char (line, *input_line_pointer++);
+ while (is_end_of_line[(unsigned char) *input_line_pointer])
+ {
+ if (*input_line_pointer == '\n')
+ {
+ bump_line_counters ();
+ LISTING_NEWLINE ();
+ }
+ ++input_line_pointer;
+ }
+ return 1;
+}
+
+/* Define a macro. This is an interface to macro.c, which is shared
+ between gas and gasp. */
+
+void
+s_macro (ignore)
+ int ignore;
+{
+ char *file;
+ unsigned int line;
+ sb s;
+ sb label;
+ const char *err;
+
+ 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));
+
+ demand_empty_rest_of_line ();
+
+ err = define_macro (0, &s, &label, get_line_sb);
+ 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);
+ line_label->sy_frag = &zero_address_frag;
+ }
+ }
+
+ sb_kill (&s);
+}
+
+/* Handle the .mexit pseudo-op, which immediately exits a macro
+ expansion. */
+
+void
+s_mexit (ignore)
+ int ignore;
+{
+ buffer_limit = input_scrub_next_buffer (&input_line_pointer);
+}
+
/* Handle changing the location counter. */
static void
@@ -1735,6 +1899,36 @@ s_mri_sect (type)
demand_empty_rest_of_line ();
}
+/* Handle the .rept pseudo-op. */
+
+void
+s_rept (ignore)
+ int ignore;
+{
+ int count;
+ sb one;
+ sb many;
+
+ count = get_absolute_expression ();
+
+ sb_new (&one);
+ if (! buffer_and_nest ("REPT", "ENDR", &one, get_line_sb))
+ {
+ as_bad ("rept without endr");
+ return;
+ }
+
+ sb_new (&many);
+ while (count-- > 0)
+ sb_add_sb (&many, &one);
+
+ sb_kill (&one);
+
+ input_scrub_include_sb (&many, input_line_pointer);
+ sb_kill (&many);
+ buffer_limit = input_scrub_next_buffer (&input_line_pointer);
+}
+
void
s_set (ignore)
int ignore;