2002-12-02 23:42:15 +08:00
|
|
|
/* macro.c - macro support for gas
|
2024-01-04 19:52:08 +08:00
|
|
|
Copyright (C) 1994-2024 Free Software Foundation, Inc.
|
1999-05-03 15:29:11 +08:00
|
|
|
|
|
|
|
Written by Steve and Judy Chamberlain of Cygnus Support,
|
|
|
|
sac@cygnus.com
|
|
|
|
|
|
|
|
This file is part of GAS, the GNU Assembler.
|
|
|
|
|
|
|
|
GAS is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
2007-07-03 19:01:12 +08:00
|
|
|
the Free Software Foundation; either version 3, or (at your option)
|
1999-05-03 15:29:11 +08:00
|
|
|
any later version.
|
|
|
|
|
|
|
|
GAS is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with GAS; see the file COPYING. If not, write to the Free
|
2005-05-05 17:13:19 +08:00
|
|
|
Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
|
|
|
|
02110-1301, USA. */
|
1999-05-03 15:29:11 +08:00
|
|
|
|
2004-10-07 23:16:08 +08:00
|
|
|
#include "as.h"
|
2001-09-19 13:33:36 +08:00
|
|
|
#include "safe-ctype.h"
|
1999-05-03 15:29:11 +08:00
|
|
|
#include "sb.h"
|
|
|
|
#include "macro.h"
|
|
|
|
|
|
|
|
/* The routines in this file handle macro definition and expansion.
|
2002-12-02 23:42:15 +08:00
|
|
|
They are called by gas. */
|
1999-05-03 15:29:11 +08:00
|
|
|
|
|
|
|
#define ISWHITE(x) ((x) == ' ' || (x) == '\t')
|
|
|
|
|
|
|
|
#define ISSEP(x) \
|
|
|
|
((x) == ' ' || (x) == '\t' || (x) == ',' || (x) == '"' || (x) == ';' \
|
|
|
|
|| (x) == ')' || (x) == '(' \
|
2023-03-17 17:06:18 +08:00
|
|
|
|| ((flag_macro_alternate || flag_mri) && ((x) == '<' || (x) == '>')))
|
1999-05-03 15:29:11 +08:00
|
|
|
|
|
|
|
#define ISBASE(x) \
|
|
|
|
((x) == 'b' || (x) == 'B' \
|
|
|
|
|| (x) == 'q' || (x) == 'Q' \
|
|
|
|
|| (x) == 'h' || (x) == 'H' \
|
|
|
|
|| (x) == 'd' || (x) == 'D')
|
|
|
|
|
|
|
|
/* The macro hash table. */
|
|
|
|
|
macro.c: use string hash from hash.h for macro_hash
Another case of duplicated hash.h code, the only minor difference
being that macro->format_hash was created with 7 entries vs. str_hash
with 16 entries.
* macro.c (macro_init, define_macro): Use str_htab_create.
(do_formals, define_macro, macro_expand_body): Use str_hash_insert
(macro_expand_body): Use str_hash_find and str_hash_delete.
(delete_macro): Likewise.
(sub_actual, macro_expand, check_macro): Use str_hash_find.
(expand_irp): Use str_htab_create and str_hash_insert.
* macro.h (struct macro_struct): Tidy.
(struct macro_hash_entry, macro_hash_entry_t, hash_macro_entry),
(eq_macro_entry, macro_entry_alloc, macro_entry_find),
(struct formal_hash_entry, formal_hash_entry_t),
(hash_formal_entry, eq_formal_entry, formal_entry_alloc),
(formal_entry_find): Delete.
* config/tc-iq2000.c (iq2000_add_macro): Use str_htab_create
and str_hash_insert.
2022-07-07 07:07:10 +08:00
|
|
|
htab_t macro_hash;
|
1999-05-03 15:29:11 +08:00
|
|
|
|
|
|
|
/* Whether any macros have been defined. */
|
|
|
|
|
|
|
|
int macro_defined;
|
|
|
|
|
|
|
|
/* Whether we should strip '@' characters. */
|
|
|
|
|
2023-03-17 17:05:32 +08:00
|
|
|
#define macro_strip_at false
|
1999-05-03 15:29:11 +08:00
|
|
|
|
|
|
|
/* Number of macro expansions that have been done. */
|
|
|
|
|
2024-05-13 16:56:09 +08:00
|
|
|
static unsigned int macro_number;
|
1999-05-03 15:29:11 +08:00
|
|
|
|
2023-01-27 08:01:56 +08:00
|
|
|
static void free_macro (macro_entry *);
|
|
|
|
|
|
|
|
static void
|
|
|
|
macro_del_f (void *ent)
|
|
|
|
{
|
|
|
|
string_tuple_t *tuple = ent;
|
|
|
|
free_macro ((macro_entry *) tuple->value);
|
|
|
|
}
|
|
|
|
|
1999-05-03 15:29:11 +08:00
|
|
|
/* Initialize macro processing. */
|
|
|
|
|
|
|
|
void
|
2023-03-17 17:06:18 +08:00
|
|
|
macro_init (void)
|
1999-05-03 15:29:11 +08:00
|
|
|
{
|
2023-01-27 08:01:56 +08:00
|
|
|
macro_hash = htab_create_alloc (16, hash_string_tuple, eq_string_tuple,
|
|
|
|
macro_del_f, notes_calloc, NULL);
|
1999-05-03 15:29:11 +08:00
|
|
|
macro_defined = 0;
|
|
|
|
}
|
|
|
|
|
2022-07-05 11:30:41 +08:00
|
|
|
void
|
|
|
|
macro_end (void)
|
|
|
|
{
|
|
|
|
htab_delete (macro_hash);
|
|
|
|
}
|
|
|
|
|
1999-05-03 15:29:11 +08:00
|
|
|
/* Read input lines till we get to a TO string.
|
|
|
|
Increase nesting depth if we get a FROM string.
|
|
|
|
Put the results into sb at PTR.
|
2005-01-31 22:30:34 +08:00
|
|
|
FROM may be NULL (or will be ignored) if TO is "ENDR".
|
1999-05-03 15:29:11 +08:00
|
|
|
Add a new input line to an sb using GET_LINE.
|
|
|
|
Return 1 on success, 0 on unexpected EOF. */
|
|
|
|
|
|
|
|
int
|
2003-11-25 01:52:33 +08:00
|
|
|
buffer_and_nest (const char *from, const char *to, sb *ptr,
|
PR gas/14201
* sb.h (sb_max_power_two): Delete.
(struct sb): Delete "item" and "pot". Make "len" a size_t. Add "max".
(sb_element): Delete.
(sb_add_char, sb_add_buffer, sb_skip_comma, sb_skip_write): Update
prototypes.
* sb.c (string_count, free_list): Delete.
(sb_build, sb_kill, sb_check): Rewrite.
(scrub_from_sb, sb_add_char, sb_add_string, sb_add_buffer,
sb_skip_white, sb_skip_comma): Replace assorted int params,
vars and return types with size_t.
* input-scrub.c: Likewise.
* macro.c: Likewise.
* macro.h: Likewise.
* as.c: Likewise.
* as.h: Likewise.
* input-file.h: Likewise.
* input-file.c: Likewise.
* read.c: Likewise.
* app.c: ..or ptrdiff_t.
* input-file.c (input_file_get): Use ferror.
(input_file_give_next_buffer): Use input_file_get.
2012-06-07 20:47:23 +08:00
|
|
|
size_t (*get_line) (sb *))
|
1999-05-03 15:29:11 +08:00
|
|
|
{
|
PR gas/14201
* sb.h (sb_max_power_two): Delete.
(struct sb): Delete "item" and "pot". Make "len" a size_t. Add "max".
(sb_element): Delete.
(sb_add_char, sb_add_buffer, sb_skip_comma, sb_skip_write): Update
prototypes.
* sb.c (string_count, free_list): Delete.
(sb_build, sb_kill, sb_check): Rewrite.
(scrub_from_sb, sb_add_char, sb_add_string, sb_add_buffer,
sb_skip_white, sb_skip_comma): Replace assorted int params,
vars and return types with size_t.
* input-scrub.c: Likewise.
* macro.c: Likewise.
* macro.h: Likewise.
* as.c: Likewise.
* as.h: Likewise.
* input-file.h: Likewise.
* input-file.c: Likewise.
* read.c: Likewise.
* app.c: ..or ptrdiff_t.
* input-file.c (input_file_get): Use ferror.
(input_file_give_next_buffer): Use input_file_get.
2012-06-07 20:47:23 +08:00
|
|
|
size_t from_len;
|
|
|
|
size_t to_len = strlen (to);
|
1999-05-03 15:29:11 +08:00
|
|
|
int depth = 1;
|
2022-12-16 16:01:14 +08:00
|
|
|
size_t line_start, more;
|
1999-05-03 15:29:11 +08:00
|
|
|
|
2011-03-30 23:10:37 +08:00
|
|
|
if (to_len == 4 && strcasecmp (to, "ENDR") == 0)
|
2005-01-31 22:30:34 +08:00
|
|
|
{
|
|
|
|
from = NULL;
|
|
|
|
from_len = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
from_len = strlen (from);
|
|
|
|
|
2022-12-13 16:11:53 +08:00
|
|
|
/* Record the present source position, such that diagnostics and debug info
|
|
|
|
can be properly associated with the respective original lines, rather
|
|
|
|
than with the line of the ending directive (TO). */
|
|
|
|
{
|
|
|
|
unsigned int line;
|
|
|
|
char *linefile;
|
|
|
|
|
|
|
|
as_where_top (&line);
|
|
|
|
if (!flag_m68k_mri)
|
|
|
|
linefile = xasprintf ("\t.linefile %u .", line + 1);
|
|
|
|
else
|
|
|
|
linefile = xasprintf ("\tlinefile %u .", line + 1);
|
|
|
|
sb_add_string (ptr, linefile);
|
|
|
|
xfree (linefile);
|
|
|
|
}
|
2022-04-12 15:03:13 +08:00
|
|
|
|
2022-12-16 16:01:14 +08:00
|
|
|
line_start = ptr->len;
|
|
|
|
more = get_line (ptr);
|
1999-05-03 15:29:11 +08:00
|
|
|
while (more)
|
|
|
|
{
|
2005-11-07 09:47:54 +08:00
|
|
|
/* Try to find the first pseudo op on the line. */
|
PR gas/14201
* sb.h (sb_max_power_two): Delete.
(struct sb): Delete "item" and "pot". Make "len" a size_t. Add "max".
(sb_element): Delete.
(sb_add_char, sb_add_buffer, sb_skip_comma, sb_skip_write): Update
prototypes.
* sb.c (string_count, free_list): Delete.
(sb_build, sb_kill, sb_check): Rewrite.
(scrub_from_sb, sb_add_char, sb_add_string, sb_add_buffer,
sb_skip_white, sb_skip_comma): Replace assorted int params,
vars and return types with size_t.
* input-scrub.c: Likewise.
* macro.c: Likewise.
* macro.h: Likewise.
* as.c: Likewise.
* as.h: Likewise.
* input-file.h: Likewise.
* input-file.c: Likewise.
* read.c: Likewise.
* app.c: ..or ptrdiff_t.
* input-file.c (input_file_get): Use ferror.
(input_file_give_next_buffer): Use input_file_get.
2012-06-07 20:47:23 +08:00
|
|
|
size_t i = line_start;
|
Use bool in gas
* as.h (POISON_BFD_BOOLEAN): Define.
* as.c, * as.h, * atof-generic.c, * config/atof-ieee.c,
* config/bfin-aux.h, * config/obj-coff.c, * config/obj-ecoff.c,
* config/obj-elf.c, * config/obj-elf.h, * config/obj-som.c,
* config/tc-aarch64.c, * config/tc-alpha.c, * config/tc-arc.c,
* config/tc-arc.h, * config/tc-arm.c, * config/tc-arm.h,
* config/tc-avr.c, * config/tc-avr.h, * config/tc-bfin.c,
* config/tc-bfin.h, * config/tc-bpf.c, * config/tc-cris.c,
* config/tc-csky.c, * config/tc-csky.h, * config/tc-d10v.c,
* config/tc-d10v.h, * config/tc-d30v.c, * config/tc-d30v.h,
* config/tc-dlx.c, * config/tc-dlx.h, * config/tc-epiphany.c,
* config/tc-epiphany.h, * config/tc-fr30.c, * config/tc-fr30.h,
* config/tc-frv.c, * config/tc-frv.h, * config/tc-ft32.c,
* config/tc-ft32.h, * config/tc-h8300.c, * config/tc-hppa.c,
* config/tc-i386-intel.c, * config/tc-i386.c, * config/tc-ia64.c,
* config/tc-ip2k.c, * config/tc-iq2000.c, * config/tc-iq2000.h,
* config/tc-lm32.c, * config/tc-lm32.h, * config/tc-m32c.c,
* config/tc-m32c.h, * config/tc-m32r.c, * config/tc-m32r.h,
* config/tc-m68hc11.c, * config/tc-m68k.c, * config/tc-mcore.c,
* config/tc-mcore.h, * config/tc-mep.c, * config/tc-mep.h,
* config/tc-metag.c, * config/tc-metag.h,
* config/tc-microblaze.c, * config/tc-mips.c, * config/tc-mips.h,
* config/tc-mmix.c, * config/tc-mn10200.c, * config/tc-mn10300.c,
* config/tc-mn10300.h, * config/tc-moxie.c, * config/tc-msp430.c,
* config/tc-msp430.h, * config/tc-mt.c, * config/tc-mt.h,
* config/tc-nds32.c, * config/tc-nds32.h, * config/tc-nios2.c,
* config/tc-ns32k.c, * config/tc-or1k.c, * config/tc-or1k.h,
* config/tc-pdp11.c, * config/tc-ppc.c, * config/tc-pru.c,
* config/tc-pru.h, * config/tc-riscv.c, * config/tc-riscv.h,
* config/tc-rx.c, * config/tc-rx.h, * config/tc-s12z.c,
* config/tc-s12z.h, * config/tc-s390.c, * config/tc-score.c,
* config/tc-score.h, * config/tc-score7.c, * config/tc-sh.c,
* config/tc-sh.h, * config/tc-spu.c, * config/tc-tic54x.c,
* config/tc-tic6x.c, * config/tc-tic6x.h, * config/tc-tilegx.c,
* config/tc-tilepro.c, * config/tc-v850.c, * config/tc-v850.h,
* config/tc-visium.c, * config/tc-visium.h, * config/tc-wasm32.c,
* config/tc-wasm32.h, * config/tc-xc16x.c, * config/tc-xgate.c,
* config/tc-xstormy16.c, * config/tc-xstormy16.h,
* config/tc-xtensa.c, * config/tc-xtensa.h, * config/tc-z80.c,
* config/tc-z8k.c, * config/xtensa-istack.h,
* config/xtensa-relax.c, * config/xtensa-relax.h, * dw2gencfi.c,
* dwarf2dbg.c, * dwarf2dbg.h, * expr.c, * expr.h, * frags.c,
* frags.h, * listing.c, * macro.c, * output-file.c, * read.c,
* read.h, * stabs.c, * symbols.c, * write.c: Replace bfd_boolean
with bool, FALSE with false, and TRUE with true.
2021-03-31 08:12:05 +08:00
|
|
|
bool had_colon = false;
|
1999-05-03 15:29:11 +08:00
|
|
|
|
2005-11-07 09:47:54 +08:00
|
|
|
/* With normal syntax we can suck what we want till we get
|
|
|
|
to the dot. With the alternate, labels have to start in
|
|
|
|
the first column, since we can't tell what's a label and
|
|
|
|
what's a pseudoop. */
|
1999-05-03 15:29:11 +08:00
|
|
|
|
2005-11-07 09:47:54 +08:00
|
|
|
if (! LABELS_WITHOUT_COLONS)
|
|
|
|
{
|
|
|
|
/* Skip leading whitespace. */
|
|
|
|
while (i < ptr->len && ISWHITE (ptr->ptr[i]))
|
|
|
|
i++;
|
|
|
|
}
|
1999-05-03 15:29:11 +08:00
|
|
|
|
2005-11-07 09:47:54 +08:00
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
/* Skip over a label, if any. */
|
|
|
|
if (i >= ptr->len || ! is_name_beginner (ptr->ptr[i]))
|
|
|
|
break;
|
|
|
|
i++;
|
|
|
|
while (i < ptr->len && is_part_of_name (ptr->ptr[i]))
|
|
|
|
i++;
|
|
|
|
if (i < ptr->len && is_name_ender (ptr->ptr[i]))
|
|
|
|
i++;
|
|
|
|
/* Skip whitespace. */
|
|
|
|
while (i < ptr->len && ISWHITE (ptr->ptr[i]))
|
|
|
|
i++;
|
|
|
|
/* Check for the colon. */
|
|
|
|
if (i >= ptr->len || ptr->ptr[i] != ':')
|
2005-04-11 20:46:38 +08:00
|
|
|
{
|
2009-10-15 18:58:34 +08:00
|
|
|
/* LABELS_WITHOUT_COLONS doesn't mean we cannot have a
|
|
|
|
colon after a label. If we do have a colon on the
|
|
|
|
first label then handle more than one label on the
|
|
|
|
line, assuming that each label has a colon. */
|
|
|
|
if (LABELS_WITHOUT_COLONS && !had_colon)
|
|
|
|
break;
|
2005-11-07 09:47:54 +08:00
|
|
|
i = line_start;
|
|
|
|
break;
|
2005-04-11 20:46:38 +08:00
|
|
|
}
|
2005-11-07 09:47:54 +08:00
|
|
|
i++;
|
|
|
|
line_start = i;
|
Use bool in gas
* as.h (POISON_BFD_BOOLEAN): Define.
* as.c, * as.h, * atof-generic.c, * config/atof-ieee.c,
* config/bfin-aux.h, * config/obj-coff.c, * config/obj-ecoff.c,
* config/obj-elf.c, * config/obj-elf.h, * config/obj-som.c,
* config/tc-aarch64.c, * config/tc-alpha.c, * config/tc-arc.c,
* config/tc-arc.h, * config/tc-arm.c, * config/tc-arm.h,
* config/tc-avr.c, * config/tc-avr.h, * config/tc-bfin.c,
* config/tc-bfin.h, * config/tc-bpf.c, * config/tc-cris.c,
* config/tc-csky.c, * config/tc-csky.h, * config/tc-d10v.c,
* config/tc-d10v.h, * config/tc-d30v.c, * config/tc-d30v.h,
* config/tc-dlx.c, * config/tc-dlx.h, * config/tc-epiphany.c,
* config/tc-epiphany.h, * config/tc-fr30.c, * config/tc-fr30.h,
* config/tc-frv.c, * config/tc-frv.h, * config/tc-ft32.c,
* config/tc-ft32.h, * config/tc-h8300.c, * config/tc-hppa.c,
* config/tc-i386-intel.c, * config/tc-i386.c, * config/tc-ia64.c,
* config/tc-ip2k.c, * config/tc-iq2000.c, * config/tc-iq2000.h,
* config/tc-lm32.c, * config/tc-lm32.h, * config/tc-m32c.c,
* config/tc-m32c.h, * config/tc-m32r.c, * config/tc-m32r.h,
* config/tc-m68hc11.c, * config/tc-m68k.c, * config/tc-mcore.c,
* config/tc-mcore.h, * config/tc-mep.c, * config/tc-mep.h,
* config/tc-metag.c, * config/tc-metag.h,
* config/tc-microblaze.c, * config/tc-mips.c, * config/tc-mips.h,
* config/tc-mmix.c, * config/tc-mn10200.c, * config/tc-mn10300.c,
* config/tc-mn10300.h, * config/tc-moxie.c, * config/tc-msp430.c,
* config/tc-msp430.h, * config/tc-mt.c, * config/tc-mt.h,
* config/tc-nds32.c, * config/tc-nds32.h, * config/tc-nios2.c,
* config/tc-ns32k.c, * config/tc-or1k.c, * config/tc-or1k.h,
* config/tc-pdp11.c, * config/tc-ppc.c, * config/tc-pru.c,
* config/tc-pru.h, * config/tc-riscv.c, * config/tc-riscv.h,
* config/tc-rx.c, * config/tc-rx.h, * config/tc-s12z.c,
* config/tc-s12z.h, * config/tc-s390.c, * config/tc-score.c,
* config/tc-score.h, * config/tc-score7.c, * config/tc-sh.c,
* config/tc-sh.h, * config/tc-spu.c, * config/tc-tic54x.c,
* config/tc-tic6x.c, * config/tc-tic6x.h, * config/tc-tilegx.c,
* config/tc-tilepro.c, * config/tc-v850.c, * config/tc-v850.h,
* config/tc-visium.c, * config/tc-visium.h, * config/tc-wasm32.c,
* config/tc-wasm32.h, * config/tc-xc16x.c, * config/tc-xgate.c,
* config/tc-xstormy16.c, * config/tc-xstormy16.h,
* config/tc-xtensa.c, * config/tc-xtensa.h, * config/tc-z80.c,
* config/tc-z8k.c, * config/xtensa-istack.h,
* config/xtensa-relax.c, * config/xtensa-relax.h, * dw2gencfi.c,
* dwarf2dbg.c, * dwarf2dbg.h, * expr.c, * expr.h, * frags.c,
* frags.h, * listing.c, * macro.c, * output-file.c, * read.c,
* read.h, * stabs.c, * symbols.c, * write.c: Replace bfd_boolean
with bool, FALSE with false, and TRUE with true.
2021-03-31 08:12:05 +08:00
|
|
|
had_colon = true;
|
1999-05-03 15:29:11 +08:00
|
|
|
}
|
2005-11-07 09:47:54 +08:00
|
|
|
|
2000-09-01 02:36:18 +08:00
|
|
|
/* Skip trailing whitespace. */
|
1999-05-03 15:29:11 +08:00
|
|
|
while (i < ptr->len && ISWHITE (ptr->ptr[i]))
|
|
|
|
i++;
|
|
|
|
|
|
|
|
if (i < ptr->len && (ptr->ptr[i] == '.'
|
2005-01-31 22:30:34 +08:00
|
|
|
|| NO_PSEUDO_DOT
|
2023-03-17 17:05:57 +08:00
|
|
|
|| flag_mri))
|
1999-05-03 15:29:11 +08:00
|
|
|
{
|
2005-01-31 22:30:34 +08:00
|
|
|
if (! flag_m68k_mri && ptr->ptr[i] == '.')
|
2000-09-01 02:36:18 +08:00
|
|
|
i++;
|
2022-03-17 13:34:22 +08:00
|
|
|
size_t len = ptr->len - i;
|
2022-02-15 12:05:14 +08:00
|
|
|
if (from == NULL)
|
|
|
|
{
|
|
|
|
if (len >= 5 && strncasecmp (ptr->ptr + i, "IREPC", 5) == 0)
|
|
|
|
from_len = 5;
|
|
|
|
else if (len >= 4 && strncasecmp (ptr->ptr + i, "IREP", 4) == 0)
|
|
|
|
from_len = 4;
|
|
|
|
else if (len >= 4 && strncasecmp (ptr->ptr + i, "IRPC", 4) == 0)
|
|
|
|
from_len = 4;
|
|
|
|
else if (len >= 4 && strncasecmp (ptr->ptr + i, "REPT", 4) == 0)
|
|
|
|
from_len = 4;
|
|
|
|
else if (len >= 3 && strncasecmp (ptr->ptr + i, "IRP", 3) == 0)
|
|
|
|
from_len = 3;
|
|
|
|
else if (len >= 3 && strncasecmp (ptr->ptr + i, "REP", 3) == 0)
|
|
|
|
from_len = 3;
|
|
|
|
else
|
|
|
|
from_len = 0;
|
|
|
|
}
|
2005-01-31 22:30:34 +08:00
|
|
|
if ((from != NULL
|
2022-03-17 13:34:22 +08:00
|
|
|
? (len >= from_len
|
|
|
|
&& strncasecmp (ptr->ptr + i, from, from_len) == 0)
|
2005-01-31 22:30:34 +08:00
|
|
|
: from_len > 0)
|
2022-03-17 13:34:22 +08:00
|
|
|
&& (len == from_len
|
2005-04-11 20:46:38 +08:00
|
|
|
|| ! (is_part_of_name (ptr->ptr[i + from_len])
|
|
|
|
|| is_name_ender (ptr->ptr[i + from_len]))))
|
1999-05-03 15:29:11 +08:00
|
|
|
depth++;
|
2022-03-17 13:34:22 +08:00
|
|
|
if (len >= to_len
|
2022-02-15 12:05:14 +08:00
|
|
|
&& strncasecmp (ptr->ptr + i, to, to_len) == 0
|
2022-03-17 13:34:22 +08:00
|
|
|
&& (len == to_len
|
2005-04-11 20:46:38 +08:00
|
|
|
|| ! (is_part_of_name (ptr->ptr[i + to_len])
|
|
|
|
|| is_name_ender (ptr->ptr[i + to_len]))))
|
1999-05-03 15:29:11 +08:00
|
|
|
{
|
|
|
|
depth--;
|
|
|
|
if (depth == 0)
|
|
|
|
{
|
2000-09-01 02:36:18 +08:00
|
|
|
/* Reset the string to not include the ending rune. */
|
1999-05-03 15:29:11 +08:00
|
|
|
ptr->len = line_start;
|
2024-08-30 17:21:58 +08:00
|
|
|
|
|
|
|
/* With the ending directive consumed here, announce the
|
|
|
|
line for macro-expanded listings. */
|
|
|
|
if (listing & LISTING_MACEXP)
|
|
|
|
listing_newline (NULL);
|
1999-05-03 15:29:11 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2014-06-18 00:21:08 +08:00
|
|
|
|
|
|
|
/* PR gas/16908
|
2022-12-13 16:11:53 +08:00
|
|
|
Apply .linefile directives that appear within the macro, alongside
|
|
|
|
keeping them for later expansion of the macro. */
|
2022-03-29 14:18:14 +08:00
|
|
|
if (from != NULL && strcasecmp (from, "MACRO") == 0
|
|
|
|
&& len >= 8 && strncasecmp (ptr->ptr + i, "linefile", 8) == 0)
|
2014-06-18 00:21:08 +08:00
|
|
|
{
|
2023-02-15 15:46:02 +08:00
|
|
|
sb_add_char (ptr, more);
|
|
|
|
temp_ilp (sb_terminate (ptr) + i + 8);
|
2022-04-12 15:04:15 +08:00
|
|
|
s_linefile (0);
|
2019-03-18 20:04:36 +08:00
|
|
|
restore_ilp ();
|
2023-02-15 15:46:02 +08:00
|
|
|
line_start = ptr->len;
|
|
|
|
more = get_line (ptr);
|
|
|
|
continue;
|
2014-06-18 00:21:08 +08:00
|
|
|
}
|
1999-05-03 15:29:11 +08:00
|
|
|
}
|
|
|
|
|
2003-03-13 19:49:33 +08:00
|
|
|
/* Add the original end-of-line char to the end and keep running. */
|
|
|
|
sb_add_char (ptr, more);
|
1999-05-03 15:29:11 +08:00
|
|
|
line_start = ptr->len;
|
|
|
|
more = get_line (ptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Return 1 on success, 0 on unexpected EOF. */
|
|
|
|
return depth == 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Pick up a token. */
|
|
|
|
|
PR gas/14201
* sb.h (sb_max_power_two): Delete.
(struct sb): Delete "item" and "pot". Make "len" a size_t. Add "max".
(sb_element): Delete.
(sb_add_char, sb_add_buffer, sb_skip_comma, sb_skip_write): Update
prototypes.
* sb.c (string_count, free_list): Delete.
(sb_build, sb_kill, sb_check): Rewrite.
(scrub_from_sb, sb_add_char, sb_add_string, sb_add_buffer,
sb_skip_white, sb_skip_comma): Replace assorted int params,
vars and return types with size_t.
* input-scrub.c: Likewise.
* macro.c: Likewise.
* macro.h: Likewise.
* as.c: Likewise.
* as.h: Likewise.
* input-file.h: Likewise.
* input-file.c: Likewise.
* read.c: Likewise.
* app.c: ..or ptrdiff_t.
* input-file.c (input_file_get): Use ferror.
(input_file_give_next_buffer): Use input_file_get.
2012-06-07 20:47:23 +08:00
|
|
|
static size_t
|
|
|
|
get_token (size_t idx, sb *in, sb *name)
|
1999-05-03 15:29:11 +08:00
|
|
|
{
|
|
|
|
if (idx < in->len
|
2005-04-11 20:46:38 +08:00
|
|
|
&& is_name_beginner (in->ptr[idx]))
|
1999-05-03 15:29:11 +08:00
|
|
|
{
|
|
|
|
sb_add_char (name, in->ptr[idx++]);
|
|
|
|
while (idx < in->len
|
2005-04-11 20:46:38 +08:00
|
|
|
&& is_part_of_name (in->ptr[idx]))
|
|
|
|
{
|
|
|
|
sb_add_char (name, in->ptr[idx++]);
|
|
|
|
}
|
|
|
|
if (idx < in->len
|
|
|
|
&& is_name_ender (in->ptr[idx]))
|
1999-05-03 15:29:11 +08:00
|
|
|
{
|
|
|
|
sb_add_char (name, in->ptr[idx++]);
|
|
|
|
}
|
|
|
|
}
|
2000-09-01 02:36:18 +08:00
|
|
|
/* Ignore trailing &. */
|
2023-03-17 17:06:18 +08:00
|
|
|
if (flag_macro_alternate && idx < in->len && in->ptr[idx] == '&')
|
1999-05-03 15:29:11 +08:00
|
|
|
idx++;
|
|
|
|
return idx;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Pick up a string. */
|
|
|
|
|
PR gas/14201
* sb.h (sb_max_power_two): Delete.
(struct sb): Delete "item" and "pot". Make "len" a size_t. Add "max".
(sb_element): Delete.
(sb_add_char, sb_add_buffer, sb_skip_comma, sb_skip_write): Update
prototypes.
* sb.c (string_count, free_list): Delete.
(sb_build, sb_kill, sb_check): Rewrite.
(scrub_from_sb, sb_add_char, sb_add_string, sb_add_buffer,
sb_skip_white, sb_skip_comma): Replace assorted int params,
vars and return types with size_t.
* input-scrub.c: Likewise.
* macro.c: Likewise.
* macro.h: Likewise.
* as.c: Likewise.
* as.h: Likewise.
* input-file.h: Likewise.
* input-file.c: Likewise.
* read.c: Likewise.
* app.c: ..or ptrdiff_t.
* input-file.c (input_file_get): Use ferror.
(input_file_give_next_buffer): Use input_file_get.
2012-06-07 20:47:23 +08:00
|
|
|
static size_t
|
|
|
|
getstring (size_t idx, sb *in, sb *acc)
|
1999-05-03 15:29:11 +08:00
|
|
|
{
|
|
|
|
while (idx < in->len
|
2000-09-01 02:36:18 +08:00
|
|
|
&& (in->ptr[idx] == '"'
|
2023-03-17 17:06:18 +08:00
|
|
|
|| (in->ptr[idx] == '<' && (flag_macro_alternate || flag_mri))
|
|
|
|
|| (in->ptr[idx] == '\'' && flag_macro_alternate)))
|
1999-05-03 15:29:11 +08:00
|
|
|
{
|
2005-08-09 23:47:46 +08:00
|
|
|
if (in->ptr[idx] == '<')
|
1999-05-03 15:29:11 +08:00
|
|
|
{
|
|
|
|
int nest = 0;
|
|
|
|
idx++;
|
2019-01-25 11:11:47 +08:00
|
|
|
while (idx < in->len
|
|
|
|
&& (in->ptr[idx] != '>' || nest))
|
1999-05-03 15:29:11 +08:00
|
|
|
{
|
|
|
|
if (in->ptr[idx] == '!')
|
|
|
|
{
|
2000-09-01 02:36:18 +08:00
|
|
|
idx++;
|
1999-05-03 15:29:11 +08:00
|
|
|
sb_add_char (acc, in->ptr[idx++]);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2006-02-28 15:55:36 +08:00
|
|
|
if (in->ptr[idx] == '>')
|
1999-05-03 15:29:11 +08:00
|
|
|
nest--;
|
2006-02-28 15:55:36 +08:00
|
|
|
if (in->ptr[idx] == '<')
|
1999-05-03 15:29:11 +08:00
|
|
|
nest++;
|
|
|
|
sb_add_char (acc, in->ptr[idx++]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
idx++;
|
|
|
|
}
|
|
|
|
else if (in->ptr[idx] == '"' || in->ptr[idx] == '\'')
|
|
|
|
{
|
|
|
|
char tchar = in->ptr[idx];
|
2000-06-14 12:58:50 +08:00
|
|
|
int escaped = 0;
|
2000-09-01 02:36:18 +08:00
|
|
|
|
1999-05-03 15:29:11 +08:00
|
|
|
idx++;
|
2000-09-01 02:36:18 +08:00
|
|
|
|
1999-05-03 15:29:11 +08:00
|
|
|
while (idx < in->len)
|
|
|
|
{
|
2000-09-01 02:36:18 +08:00
|
|
|
if (in->ptr[idx - 1] == '\\')
|
2000-06-14 12:58:50 +08:00
|
|
|
escaped ^= 1;
|
|
|
|
else
|
|
|
|
escaped = 0;
|
|
|
|
|
2023-03-17 17:06:18 +08:00
|
|
|
if (flag_macro_alternate && in->ptr[idx] == '!')
|
1999-05-03 15:29:11 +08:00
|
|
|
{
|
2000-12-13 03:29:24 +08:00
|
|
|
idx ++;
|
2000-09-01 02:36:18 +08:00
|
|
|
|
2000-06-26 01:59:22 +08:00
|
|
|
sb_add_char (acc, in->ptr[idx]);
|
|
|
|
|
2000-12-13 03:29:24 +08:00
|
|
|
idx ++;
|
1999-05-03 15:29:11 +08:00
|
|
|
}
|
2000-06-14 12:58:50 +08:00
|
|
|
else if (escaped && in->ptr[idx] == tchar)
|
|
|
|
{
|
|
|
|
sb_add_char (acc, tchar);
|
2000-12-13 03:29:24 +08:00
|
|
|
idx ++;
|
2000-06-14 12:58:50 +08:00
|
|
|
}
|
1999-05-03 15:29:11 +08:00
|
|
|
else
|
|
|
|
{
|
|
|
|
if (in->ptr[idx] == tchar)
|
|
|
|
{
|
2000-12-13 03:29:24 +08:00
|
|
|
idx ++;
|
2000-09-01 02:36:18 +08:00
|
|
|
|
1999-05-03 15:29:11 +08:00
|
|
|
if (idx >= in->len || in->ptr[idx] != tchar)
|
|
|
|
break;
|
|
|
|
}
|
2000-09-01 02:36:18 +08:00
|
|
|
|
1999-05-03 15:29:11 +08:00
|
|
|
sb_add_char (acc, in->ptr[idx]);
|
2000-12-13 03:29:24 +08:00
|
|
|
idx ++;
|
1999-05-03 15:29:11 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2000-09-01 02:36:18 +08:00
|
|
|
|
1999-05-03 15:29:11 +08:00
|
|
|
return idx;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Fetch string from the input stream,
|
|
|
|
rules:
|
|
|
|
'Bxyx<whitespace> -> return 'Bxyza
|
2005-08-08 19:15:33 +08:00
|
|
|
%<expr> -> return string of decimal value of <expr>
|
|
|
|
"string" -> return string
|
2005-08-09 23:47:46 +08:00
|
|
|
(string) -> return (string-including-whitespaces)
|
2005-08-08 19:15:33 +08:00
|
|
|
xyx<whitespace> -> return xyz. */
|
1999-05-03 15:29:11 +08:00
|
|
|
|
PR gas/14201
* sb.h (sb_max_power_two): Delete.
(struct sb): Delete "item" and "pot". Make "len" a size_t. Add "max".
(sb_element): Delete.
(sb_add_char, sb_add_buffer, sb_skip_comma, sb_skip_write): Update
prototypes.
* sb.c (string_count, free_list): Delete.
(sb_build, sb_kill, sb_check): Rewrite.
(scrub_from_sb, sb_add_char, sb_add_string, sb_add_buffer,
sb_skip_white, sb_skip_comma): Replace assorted int params,
vars and return types with size_t.
* input-scrub.c: Likewise.
* macro.c: Likewise.
* macro.h: Likewise.
* as.c: Likewise.
* as.h: Likewise.
* input-file.h: Likewise.
* input-file.c: Likewise.
* read.c: Likewise.
* app.c: ..or ptrdiff_t.
* input-file.c (input_file_get): Use ferror.
(input_file_give_next_buffer): Use input_file_get.
2012-06-07 20:47:23 +08:00
|
|
|
static size_t
|
|
|
|
get_any_string (size_t idx, sb *in, sb *out)
|
1999-05-03 15:29:11 +08:00
|
|
|
{
|
|
|
|
sb_reset (out);
|
|
|
|
idx = sb_skip_white (idx, in);
|
|
|
|
|
|
|
|
if (idx < in->len)
|
|
|
|
{
|
2002-11-11 16:42:52 +08:00
|
|
|
if (in->len > idx + 2 && in->ptr[idx + 1] == '\'' && ISBASE (in->ptr[idx]))
|
1999-05-03 15:29:11 +08:00
|
|
|
{
|
2019-01-05 00:18:59 +08:00
|
|
|
while (idx < in->len && !ISSEP (in->ptr[idx]))
|
1999-05-03 15:29:11 +08:00
|
|
|
sb_add_char (out, in->ptr[idx++]);
|
|
|
|
}
|
2023-03-17 17:06:18 +08:00
|
|
|
else if (in->ptr[idx] == '%' && flag_macro_alternate)
|
1999-05-03 15:29:11 +08:00
|
|
|
{
|
2023-03-17 17:05:05 +08:00
|
|
|
/* Turn the following expression into a string. */
|
|
|
|
expressionS ex;
|
2019-05-10 23:57:31 +08:00
|
|
|
char buf[64];
|
2005-08-08 19:15:33 +08:00
|
|
|
|
2023-03-17 17:05:05 +08:00
|
|
|
sb_terminate (in);
|
|
|
|
|
|
|
|
temp_ilp (in->ptr + idx + 1);
|
|
|
|
expression_and_evaluate (&ex);
|
|
|
|
idx = input_line_pointer - in->ptr;
|
|
|
|
restore_ilp ();
|
|
|
|
|
|
|
|
if (ex.X_op != O_constant)
|
|
|
|
as_bad (_("%% operator needs absolute expression"));
|
|
|
|
|
|
|
|
sprintf (buf, "%" PRId64, (int64_t) ex.X_add_number);
|
1999-05-03 15:29:11 +08:00
|
|
|
sb_add_string (out, buf);
|
|
|
|
}
|
|
|
|
else if (in->ptr[idx] == '"'
|
2023-03-17 17:06:18 +08:00
|
|
|
|| (in->ptr[idx] == '<' && (flag_macro_alternate || flag_mri))
|
|
|
|
|| (flag_macro_alternate && in->ptr[idx] == '\''))
|
1999-05-03 15:29:11 +08:00
|
|
|
{
|
2023-03-17 17:06:18 +08:00
|
|
|
if (flag_macro_alternate && ! macro_strip_at && in->ptr[idx] != '<')
|
1999-05-03 15:29:11 +08:00
|
|
|
{
|
2000-09-01 02:36:18 +08:00
|
|
|
/* Keep the quotes. */
|
2006-02-28 15:57:09 +08:00
|
|
|
sb_add_char (out, '"');
|
1999-05-03 15:29:11 +08:00
|
|
|
idx = getstring (idx, in, out);
|
2006-02-28 15:57:09 +08:00
|
|
|
sb_add_char (out, '"');
|
1999-05-03 15:29:11 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
idx = getstring (idx, in, out);
|
|
|
|
}
|
|
|
|
}
|
2000-09-01 02:36:18 +08:00
|
|
|
else
|
1999-05-03 15:29:11 +08:00
|
|
|
{
|
2016-04-07 04:26:46 +08:00
|
|
|
char *br_buf = XNEWVEC (char, 1);
|
2006-02-28 15:55:36 +08:00
|
|
|
char *in_br = br_buf;
|
|
|
|
|
|
|
|
*in_br = '\0';
|
2000-09-01 02:36:18 +08:00
|
|
|
while (idx < in->len
|
2006-02-28 15:55:36 +08:00
|
|
|
&& (*in_br
|
|
|
|
|| (in->ptr[idx] != ' '
|
|
|
|
&& in->ptr[idx] != '\t'))
|
2005-05-10 15:48:24 +08:00
|
|
|
&& in->ptr[idx] != ','
|
|
|
|
&& (in->ptr[idx] != '<'
|
2023-03-17 17:06:18 +08:00
|
|
|
|| (! flag_macro_alternate && ! flag_mri)))
|
1999-05-03 15:29:11 +08:00
|
|
|
{
|
2006-02-28 15:55:36 +08:00
|
|
|
char tchar = in->ptr[idx];
|
2005-08-08 19:15:33 +08:00
|
|
|
|
2006-02-28 15:55:36 +08:00
|
|
|
switch (tchar)
|
|
|
|
{
|
|
|
|
case '"':
|
|
|
|
case '\'':
|
1999-05-03 15:29:11 +08:00
|
|
|
sb_add_char (out, in->ptr[idx++]);
|
|
|
|
while (idx < in->len
|
|
|
|
&& in->ptr[idx] != tchar)
|
2000-09-01 02:36:18 +08:00
|
|
|
sb_add_char (out, in->ptr[idx++]);
|
1999-05-03 15:29:11 +08:00
|
|
|
if (idx == in->len)
|
2011-03-30 23:10:37 +08:00
|
|
|
{
|
|
|
|
free (br_buf);
|
|
|
|
return idx;
|
|
|
|
}
|
2006-02-28 15:55:36 +08:00
|
|
|
break;
|
|
|
|
case '(':
|
|
|
|
case '[':
|
|
|
|
if (in_br > br_buf)
|
|
|
|
--in_br;
|
|
|
|
else
|
|
|
|
{
|
2016-04-07 04:26:46 +08:00
|
|
|
br_buf = XNEWVEC (char, strlen (in_br) + 2);
|
2011-03-30 23:10:37 +08:00
|
|
|
strcpy (br_buf + 1, in_br);
|
|
|
|
free (in_br);
|
2006-02-28 15:55:36 +08:00
|
|
|
in_br = br_buf;
|
|
|
|
}
|
|
|
|
*in_br = tchar;
|
|
|
|
break;
|
|
|
|
case ')':
|
|
|
|
if (*in_br == '(')
|
|
|
|
++in_br;
|
|
|
|
break;
|
|
|
|
case ']':
|
|
|
|
if (*in_br == '[')
|
|
|
|
++in_br;
|
|
|
|
break;
|
1999-05-03 15:29:11 +08:00
|
|
|
}
|
2006-02-28 15:55:36 +08:00
|
|
|
sb_add_char (out, tchar);
|
|
|
|
++idx;
|
1999-05-03 15:29:11 +08:00
|
|
|
}
|
2011-03-30 23:10:37 +08:00
|
|
|
free (br_buf);
|
1999-05-03 15:29:11 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return idx;
|
|
|
|
}
|
|
|
|
|
2005-05-06 14:50:31 +08:00
|
|
|
/* Allocate a new formal. */
|
|
|
|
|
|
|
|
static formal_entry *
|
|
|
|
new_formal (void)
|
|
|
|
{
|
|
|
|
formal_entry *formal;
|
|
|
|
|
2016-04-01 21:26:30 +08:00
|
|
|
formal = XNEW (formal_entry);
|
2005-05-06 14:50:31 +08:00
|
|
|
|
|
|
|
sb_new (&formal->name);
|
|
|
|
sb_new (&formal->def);
|
|
|
|
sb_new (&formal->actual);
|
|
|
|
formal->next = NULL;
|
|
|
|
formal->type = FORMAL_OPTIONAL;
|
|
|
|
return formal;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Free a formal. */
|
|
|
|
|
|
|
|
static void
|
|
|
|
del_formal (formal_entry *formal)
|
|
|
|
{
|
|
|
|
sb_kill (&formal->actual);
|
|
|
|
sb_kill (&formal->def);
|
|
|
|
sb_kill (&formal->name);
|
|
|
|
free (formal);
|
|
|
|
}
|
|
|
|
|
1999-05-03 15:29:11 +08:00
|
|
|
/* Pick up the formal parameters of a macro definition. */
|
|
|
|
|
PR gas/14201
* sb.h (sb_max_power_two): Delete.
(struct sb): Delete "item" and "pot". Make "len" a size_t. Add "max".
(sb_element): Delete.
(sb_add_char, sb_add_buffer, sb_skip_comma, sb_skip_write): Update
prototypes.
* sb.c (string_count, free_list): Delete.
(sb_build, sb_kill, sb_check): Rewrite.
(scrub_from_sb, sb_add_char, sb_add_string, sb_add_buffer,
sb_skip_white, sb_skip_comma): Replace assorted int params,
vars and return types with size_t.
* input-scrub.c: Likewise.
* macro.c: Likewise.
* macro.h: Likewise.
* as.c: Likewise.
* as.h: Likewise.
* input-file.h: Likewise.
* input-file.c: Likewise.
* read.c: Likewise.
* app.c: ..or ptrdiff_t.
* input-file.c (input_file_get): Use ferror.
(input_file_give_next_buffer): Use input_file_get.
2012-06-07 20:47:23 +08:00
|
|
|
static size_t
|
|
|
|
do_formals (macro_entry *macro, size_t idx, sb *in)
|
1999-05-03 15:29:11 +08:00
|
|
|
{
|
|
|
|
formal_entry **p = ¯o->formals;
|
2005-04-25 14:43:46 +08:00
|
|
|
const char *name;
|
1999-05-03 15:29:11 +08:00
|
|
|
|
2005-01-31 22:26:13 +08:00
|
|
|
idx = sb_skip_white (idx, in);
|
1999-05-03 15:29:11 +08:00
|
|
|
while (idx < in->len)
|
|
|
|
{
|
2005-05-06 14:50:31 +08:00
|
|
|
formal_entry *formal = new_formal ();
|
PR gas/14201
* sb.h (sb_max_power_two): Delete.
(struct sb): Delete "item" and "pot". Make "len" a size_t. Add "max".
(sb_element): Delete.
(sb_add_char, sb_add_buffer, sb_skip_comma, sb_skip_write): Update
prototypes.
* sb.c (string_count, free_list): Delete.
(sb_build, sb_kill, sb_check): Rewrite.
(scrub_from_sb, sb_add_char, sb_add_string, sb_add_buffer,
sb_skip_white, sb_skip_comma): Replace assorted int params,
vars and return types with size_t.
* input-scrub.c: Likewise.
* macro.c: Likewise.
* macro.h: Likewise.
* as.c: Likewise.
* as.h: Likewise.
* input-file.h: Likewise.
* input-file.c: Likewise.
* read.c: Likewise.
* app.c: ..or ptrdiff_t.
* input-file.c (input_file_get): Use ferror.
(input_file_give_next_buffer): Use input_file_get.
2012-06-07 20:47:23 +08:00
|
|
|
size_t cidx;
|
1999-05-03 15:29:11 +08:00
|
|
|
|
|
|
|
idx = get_token (idx, in, &formal->name);
|
|
|
|
if (formal->name.len == 0)
|
2005-01-31 22:26:13 +08:00
|
|
|
{
|
|
|
|
if (macro->formal_count)
|
|
|
|
--idx;
|
2011-03-30 23:10:37 +08:00
|
|
|
del_formal (formal); /* 'formal' goes out of scope. */
|
2005-01-31 22:26:13 +08:00
|
|
|
break;
|
|
|
|
}
|
1999-05-03 15:29:11 +08:00
|
|
|
idx = sb_skip_white (idx, in);
|
2005-01-31 22:26:13 +08:00
|
|
|
/* This is a formal. */
|
2005-05-06 14:50:31 +08:00
|
|
|
name = sb_terminate (&formal->name);
|
2023-03-17 17:05:57 +08:00
|
|
|
if (! flag_mri
|
2005-05-06 14:50:31 +08:00
|
|
|
&& idx < in->len
|
|
|
|
&& in->ptr[idx] == ':'
|
|
|
|
&& (! is_name_beginner (':')
|
|
|
|
|| idx + 1 >= in->len
|
|
|
|
|| ! is_part_of_name (in->ptr[idx + 1])))
|
|
|
|
{
|
|
|
|
/* Got a qualifier. */
|
|
|
|
sb qual;
|
|
|
|
|
|
|
|
sb_new (&qual);
|
|
|
|
idx = get_token (sb_skip_white (idx + 1, in), in, &qual);
|
|
|
|
sb_terminate (&qual);
|
|
|
|
if (qual.len == 0)
|
|
|
|
as_bad_where (macro->file,
|
|
|
|
macro->line,
|
|
|
|
_("Missing parameter qualifier for `%s' in macro `%s'"),
|
|
|
|
name,
|
|
|
|
macro->name);
|
|
|
|
else if (strcmp (qual.ptr, "req") == 0)
|
|
|
|
formal->type = FORMAL_REQUIRED;
|
|
|
|
else if (strcmp (qual.ptr, "vararg") == 0)
|
|
|
|
formal->type = FORMAL_VARARG;
|
|
|
|
else
|
|
|
|
as_bad_where (macro->file,
|
|
|
|
macro->line,
|
|
|
|
_("`%s' is not a valid parameter qualifier for `%s' in macro `%s'"),
|
|
|
|
qual.ptr,
|
|
|
|
name,
|
|
|
|
macro->name);
|
|
|
|
sb_kill (&qual);
|
|
|
|
idx = sb_skip_white (idx, in);
|
|
|
|
}
|
2005-01-31 22:26:13 +08:00
|
|
|
if (idx < in->len && in->ptr[idx] == '=')
|
1999-05-03 15:29:11 +08:00
|
|
|
{
|
2005-01-31 22:26:13 +08:00
|
|
|
/* Got a default. */
|
2005-05-10 15:48:24 +08:00
|
|
|
idx = get_any_string (idx + 1, in, &formal->def);
|
2005-01-31 22:26:13 +08:00
|
|
|
idx = sb_skip_white (idx, in);
|
2005-05-06 14:50:31 +08:00
|
|
|
if (formal->type == FORMAL_REQUIRED)
|
|
|
|
{
|
|
|
|
sb_reset (&formal->def);
|
|
|
|
as_warn_where (macro->file,
|
|
|
|
macro->line,
|
|
|
|
_("Pointless default value for required parameter `%s' in macro `%s'"),
|
|
|
|
name,
|
|
|
|
macro->name);
|
|
|
|
}
|
1999-05-03 15:29:11 +08:00
|
|
|
}
|
|
|
|
|
2000-09-01 02:36:18 +08:00
|
|
|
/* Add to macro's hash table. */
|
macro.c: use string hash from hash.h for macro_hash
Another case of duplicated hash.h code, the only minor difference
being that macro->format_hash was created with 7 entries vs. str_hash
with 16 entries.
* macro.c (macro_init, define_macro): Use str_htab_create.
(do_formals, define_macro, macro_expand_body): Use str_hash_insert
(macro_expand_body): Use str_hash_find and str_hash_delete.
(delete_macro): Likewise.
(sub_actual, macro_expand, check_macro): Use str_hash_find.
(expand_irp): Use str_htab_create and str_hash_insert.
* macro.h (struct macro_struct): Tidy.
(struct macro_hash_entry, macro_hash_entry_t, hash_macro_entry),
(eq_macro_entry, macro_entry_alloc, macro_entry_find),
(struct formal_hash_entry, formal_hash_entry_t),
(hash_formal_entry, eq_formal_entry, formal_entry_alloc),
(formal_entry_find): Delete.
* config/tc-iq2000.c (iq2000_add_macro): Use str_htab_create
and str_hash_insert.
2022-07-07 07:07:10 +08:00
|
|
|
if (str_hash_insert (macro->formal_hash, name, formal, 0) != NULL)
|
PR26513, 629310abec breaks assembling PowerPC Linux kernels
Inserting with replacement is wrong for some gas hash table uses.
This patch implements an htab_insert that conditionally replaces, and
similarly for str_hash_insert. str_hash_insert with replace=0 is
roughly equivalent to the older hash_insert, and str_hash_insert with
replace=1 to the older hash_jam, but return values are different. I
found it useful to know whether the slot was occupied prior to
inserting/replacing. I've also reinstated the fatal errors on messing
up opcode tables with duplicates.
PR 26513
* hash.h (htab_insert): Update prototype and comment.
(struct string_tuple): Make "value" a const void*.
(string_tuple_alloc): Likewise.
(str_hash_find, str_hash_find_n): Cast returned value.
(str_hash_insert): Add "replace" parameter, and return slot pointer.
Free alloc'd element when not inserted.
* hash.c (htab_insert): Likewise. Return slot when element exists,
otherwise return NULL.
* read.c (pop_insert): Insert into hash table without first searching.
* config/tc-avr.c (md_begin): Likewise.
* config/tc-msp430.c (md_begin): Likewise.
* config/tc-nds32.c (nds32_init_nds32_pseudo_opcodes): Likewise.
* config/tc-v850.c (md_begin): Likewise.
* macro.c (do_formals, define_macro, macro_expand_body): Likewise.
(delete_macro): Delete from hash table.
* config/tc-tic54x.c (subsym_create_or_replace): Correct logic.
* symbols.c (local_symbol_make, symbol_table_insert): Allow
replacement of hash table entries.
* config/obj-coff-seh.c (seh_hash_insert): Likewise.
* config/obj-coff.c (tag_insert): Likewise.
* config/tc-iq2000.c (iq2000_add_macro): Likewise.
* config/tc-m68k.c (md_begin): Likewise for aliases.
* config/tc-tic4x.c (tic4x_asg): Likewise.
* config/tc-tic6x.c (md_begin): Likewise.
* dw2gencfi.c (dwcfi_hash_find_or_make): Disallow replacement of
hash table entries.
* ecoff.c (add_string, get_tag): Likewise.
* macro.c (expand_irp): Likewise.
* config/obj-elf.c (build_additional_section_info): Likewise.
* config/tc-aarch64.c (insert_reg_alias): Likewise.
(checked_hash_insert): Likewise.
* config/tc-alpha.c (get_alpha_reloc_tag, md_begin): Likewise.
* config/tc-arc.c (arc_insert_opcode, declare_register): Likewise.
(declare_addrtype, md_begin, arc_extcorereg): Likewise.
* config/tc-arm.c (insert_reg_alias): Likewise.
(arm_tc_equal_in_insn, md_begin): Likewise.
* config/tc-cr16.c (initialise_reg_hash_table, md_begin): Likewise.
* config/tc-cris.c (md_begin): Likewise.
* config/tc-crx.c (md_begin): Likewise.
* config/tc-csky.c (md_begin): Likewise.
* config/tc-d10v.c (md_begin): Likewise.
* config/tc-dlx.c (md_begin): Likewise.
* config/tc-ft32.c (md_begin): Likewise.
* config/tc-h8300.c (md_begin): Likewise.
* config/tc-hppa.c (md_begin): Likewise.
* config/tc-i386.c (md_begin): Likewise.
* config/tc-ia64.c (dot_rot, dot_entry, declare_register): Likewise.
(md_begin, dot_alias): Likewise.
* config/tc-m68hc11.c (md_begin): Likewise.
* config/tc-m68k.c (md_begin): Likewise.
* config/tc-mcore.c (md_begin): Likewise.
* config/tc-microblaze.c (md_begin): Likewise.
* config/tc-mips.c (md_begin): Likewise.
* config/tc-mmix.c (md_begin): Likewise.
* config/tc-mn10200.c (md_begin): Likewise.
* config/tc-mn10300.c (md_begin): Likewise.
* config/tc-moxie.c (md_begin): Likewise.
* config/tc-nds32.c (nds32_relax_hint, md_begin): Likewise.
* config/tc-nios2.c (md_begin): Likewise.
* config/tc-ns32k.c (md_begin): Likewise.
* config/tc-pdp11.c (md_begin): Likewise.
* config/tc-pj.c (fake_opcode, md_begin): Likewise.
* config/tc-ppc.c (ppc_setup_opcodes): Likewise.
* config/tc-pru.c (md_begin): Likewise.
* config/tc-riscv.c (init_ext_version_hash): Likewise.
(init_opcode_names_hash, hash_reg_name, init_opcode_hash): Likewise.
(riscv_init_csr_hash): Likewise.
* config/tc-s390.c (s390_setup_opcodes, md_begin): Likewise.
* config/tc-score.c (s3_insert_reg): Likewise.
(s3_build_score_ops_hsh, s3_build_dependency_insn_hsh): Likewise.
* config/tc-score7.c (s7_build_score_ops_hsh): Likewise.
(s7_build_dependency_insn_hsh, s7_insert_reg): Likewise.
* config/tc-sh.c (md_begin): Likewise.
* config/tc-sparc.c (md_begin): Likewise.
* config/tc-spu.c (md_begin): Likewise.
* config/tc-tic30.c (md_begin): Likewise.
* config/tc-tic4x.c (tic4x_inst_insert): Likewise.
* config/tc-tic54x.c (stag_add_field_symbols, md_begin): Likewise.
(tic54x_endstruct, tic54x_var, tic54x_macro_info): Likewise.
(subsym_substitute): Likewise.
* config/tc-tilegx.c (md_begin): Likewise.
* config/tc-tilepro.c (md_begin): Likewise.
* config/tc-vax.c (vip_begin): Likewise.
* config/tc-wasm32.c (md_begin): Likewise.
* config/tc-xgate.c (md_begin): Likewise.
* config/tc-z8k.c (md_begin): Likewise.
* testsuite/gas/ppc/dcbt.d,
* testsuite/gas/ppc/dcbt.s: New test.
* testsuite/gas/ppc/ppc.exp: Run it.
* ecoff.c (add_string): Report fatal error on duplicates.
* config/tc-alpha.c (md_begin): Likewise.
* config/tc-arc.c (arc_insert_opcode, declare_register): Likewise.
(declare_addrtype, md_begin, arc_extcorereg): Likewise.
* config/tc-cr16.c (initialise_reg_hash_table, md_begin): Likewise.
* config/tc-cris.c (md_begin): Likewise.
* config/tc-crx.c (md_begin): Likewise.
* config/tc-dlx.c (md_begin): Likewise.
* config/tc-hppa.c (md_begin): Likewise.
* config/tc-i386.c (md_begin): Likewise.
* config/tc-ia64.c (dot_rot, dot_entry, declare_register): Likewise.
(md_begin): Likewise.
* config/tc-m68k.c (md_begin): Likewise.
* config/tc-mips.c (md_begin): Likewise.
* config/tc-nios2.c (md_begin): Likewise.
* config/tc-ns32k.c (md_begin): Likewise.
* config/tc-ppc.c (ppc_setup_opcodes): Likewise.
* config/tc-pru.c (md_begin): Likewise.
* config/tc-riscv.c (init_ext_version_hash): Likewise.
(init_opcode_names_hash, hash_reg_name, init_opcode_hash): Likewise.
* config/tc-s390.c (s390_setup_opcodes, md_begin): Likewise.
* config/tc-sparc.c (md_begin): Likewise.
* config/tc-tic30.c (md_begin): Likewise.
* config/tc-tic4x.c (tic4x_inst_insert): Likewise.
* config/tc-tilegx.c (md_begin): Likewise.
* config/tc-tilepro.c (md_begin): Likewise.
* config/tc-vax.c (vip_begin): Likewise.
* config/tc-alpha.c,
* config/tc-arm.c,
* config/tc-avr.c,
* config/tc-cr16.c,
* config/tc-csky.c,
* config/tc-i386.c,
* config/tc-m68hc11.c,
* config/tc-m68k.c,
* config/tc-microblaze.c,
* config/tc-ns32k.c,
* config/tc-pj.c,
* config/tc-ppc.c,
* config/tc-score.c,
* config/tc-score7.c,
* config/tc-tic4x.c,
* config/tc-tic54x.c,
* config/tc-tilegx.c,
* config/tc-tilepro.c,
* config/tc-xgate.c: Formatting.
2020-08-22 16:29:57 +08:00
|
|
|
{
|
|
|
|
as_bad_where (macro->file, macro->line,
|
|
|
|
_("A parameter named `%s' "
|
|
|
|
"already exists for macro `%s'"),
|
|
|
|
name, macro->name);
|
|
|
|
}
|
1999-05-03 15:29:11 +08:00
|
|
|
|
2005-01-31 22:26:13 +08:00
|
|
|
formal->index = macro->formal_count++;
|
2005-05-06 14:50:31 +08:00
|
|
|
*p = formal;
|
|
|
|
p = &formal->next;
|
|
|
|
if (formal->type == FORMAL_VARARG)
|
|
|
|
break;
|
2005-01-31 22:26:13 +08:00
|
|
|
cidx = idx;
|
1999-05-03 15:29:11 +08:00
|
|
|
idx = sb_skip_comma (idx, in);
|
2005-01-31 22:26:13 +08:00
|
|
|
if (idx != cidx && idx >= in->len)
|
|
|
|
{
|
|
|
|
idx = cidx;
|
|
|
|
break;
|
|
|
|
}
|
1999-05-03 15:29:11 +08:00
|
|
|
}
|
|
|
|
|
2023-03-17 17:05:57 +08:00
|
|
|
if (flag_mri)
|
1999-05-03 15:29:11 +08:00
|
|
|
{
|
2005-05-06 14:50:31 +08:00
|
|
|
formal_entry *formal = new_formal ();
|
1999-05-03 15:29:11 +08:00
|
|
|
|
|
|
|
/* Add a special NARG formal, which macro_expand will set to the
|
2013-01-11 01:11:17 +08:00
|
|
|
number of arguments. */
|
1999-05-03 15:29:11 +08:00
|
|
|
/* The same MRI assemblers which treat '@' characters also use
|
2013-01-11 01:11:17 +08:00
|
|
|
the name $NARG. At least until we find an exception. */
|
1999-05-03 15:29:11 +08:00
|
|
|
if (macro_strip_at)
|
|
|
|
name = "$NARG";
|
|
|
|
else
|
|
|
|
name = "NARG";
|
|
|
|
|
|
|
|
sb_add_string (&formal->name, name);
|
|
|
|
|
2000-09-01 02:36:18 +08:00
|
|
|
/* Add to macro's hash table. */
|
macro.c: use string hash from hash.h for macro_hash
Another case of duplicated hash.h code, the only minor difference
being that macro->format_hash was created with 7 entries vs. str_hash
with 16 entries.
* macro.c (macro_init, define_macro): Use str_htab_create.
(do_formals, define_macro, macro_expand_body): Use str_hash_insert
(macro_expand_body): Use str_hash_find and str_hash_delete.
(delete_macro): Likewise.
(sub_actual, macro_expand, check_macro): Use str_hash_find.
(expand_irp): Use str_htab_create and str_hash_insert.
* macro.h (struct macro_struct): Tidy.
(struct macro_hash_entry, macro_hash_entry_t, hash_macro_entry),
(eq_macro_entry, macro_entry_alloc, macro_entry_find),
(struct formal_hash_entry, formal_hash_entry_t),
(hash_formal_entry, eq_formal_entry, formal_entry_alloc),
(formal_entry_find): Delete.
* config/tc-iq2000.c (iq2000_add_macro): Use str_htab_create
and str_hash_insert.
2022-07-07 07:07:10 +08:00
|
|
|
if (str_hash_insert (macro->formal_hash, name, formal, 0) != NULL)
|
PR26513, 629310abec breaks assembling PowerPC Linux kernels
Inserting with replacement is wrong for some gas hash table uses.
This patch implements an htab_insert that conditionally replaces, and
similarly for str_hash_insert. str_hash_insert with replace=0 is
roughly equivalent to the older hash_insert, and str_hash_insert with
replace=1 to the older hash_jam, but return values are different. I
found it useful to know whether the slot was occupied prior to
inserting/replacing. I've also reinstated the fatal errors on messing
up opcode tables with duplicates.
PR 26513
* hash.h (htab_insert): Update prototype and comment.
(struct string_tuple): Make "value" a const void*.
(string_tuple_alloc): Likewise.
(str_hash_find, str_hash_find_n): Cast returned value.
(str_hash_insert): Add "replace" parameter, and return slot pointer.
Free alloc'd element when not inserted.
* hash.c (htab_insert): Likewise. Return slot when element exists,
otherwise return NULL.
* read.c (pop_insert): Insert into hash table without first searching.
* config/tc-avr.c (md_begin): Likewise.
* config/tc-msp430.c (md_begin): Likewise.
* config/tc-nds32.c (nds32_init_nds32_pseudo_opcodes): Likewise.
* config/tc-v850.c (md_begin): Likewise.
* macro.c (do_formals, define_macro, macro_expand_body): Likewise.
(delete_macro): Delete from hash table.
* config/tc-tic54x.c (subsym_create_or_replace): Correct logic.
* symbols.c (local_symbol_make, symbol_table_insert): Allow
replacement of hash table entries.
* config/obj-coff-seh.c (seh_hash_insert): Likewise.
* config/obj-coff.c (tag_insert): Likewise.
* config/tc-iq2000.c (iq2000_add_macro): Likewise.
* config/tc-m68k.c (md_begin): Likewise for aliases.
* config/tc-tic4x.c (tic4x_asg): Likewise.
* config/tc-tic6x.c (md_begin): Likewise.
* dw2gencfi.c (dwcfi_hash_find_or_make): Disallow replacement of
hash table entries.
* ecoff.c (add_string, get_tag): Likewise.
* macro.c (expand_irp): Likewise.
* config/obj-elf.c (build_additional_section_info): Likewise.
* config/tc-aarch64.c (insert_reg_alias): Likewise.
(checked_hash_insert): Likewise.
* config/tc-alpha.c (get_alpha_reloc_tag, md_begin): Likewise.
* config/tc-arc.c (arc_insert_opcode, declare_register): Likewise.
(declare_addrtype, md_begin, arc_extcorereg): Likewise.
* config/tc-arm.c (insert_reg_alias): Likewise.
(arm_tc_equal_in_insn, md_begin): Likewise.
* config/tc-cr16.c (initialise_reg_hash_table, md_begin): Likewise.
* config/tc-cris.c (md_begin): Likewise.
* config/tc-crx.c (md_begin): Likewise.
* config/tc-csky.c (md_begin): Likewise.
* config/tc-d10v.c (md_begin): Likewise.
* config/tc-dlx.c (md_begin): Likewise.
* config/tc-ft32.c (md_begin): Likewise.
* config/tc-h8300.c (md_begin): Likewise.
* config/tc-hppa.c (md_begin): Likewise.
* config/tc-i386.c (md_begin): Likewise.
* config/tc-ia64.c (dot_rot, dot_entry, declare_register): Likewise.
(md_begin, dot_alias): Likewise.
* config/tc-m68hc11.c (md_begin): Likewise.
* config/tc-m68k.c (md_begin): Likewise.
* config/tc-mcore.c (md_begin): Likewise.
* config/tc-microblaze.c (md_begin): Likewise.
* config/tc-mips.c (md_begin): Likewise.
* config/tc-mmix.c (md_begin): Likewise.
* config/tc-mn10200.c (md_begin): Likewise.
* config/tc-mn10300.c (md_begin): Likewise.
* config/tc-moxie.c (md_begin): Likewise.
* config/tc-nds32.c (nds32_relax_hint, md_begin): Likewise.
* config/tc-nios2.c (md_begin): Likewise.
* config/tc-ns32k.c (md_begin): Likewise.
* config/tc-pdp11.c (md_begin): Likewise.
* config/tc-pj.c (fake_opcode, md_begin): Likewise.
* config/tc-ppc.c (ppc_setup_opcodes): Likewise.
* config/tc-pru.c (md_begin): Likewise.
* config/tc-riscv.c (init_ext_version_hash): Likewise.
(init_opcode_names_hash, hash_reg_name, init_opcode_hash): Likewise.
(riscv_init_csr_hash): Likewise.
* config/tc-s390.c (s390_setup_opcodes, md_begin): Likewise.
* config/tc-score.c (s3_insert_reg): Likewise.
(s3_build_score_ops_hsh, s3_build_dependency_insn_hsh): Likewise.
* config/tc-score7.c (s7_build_score_ops_hsh): Likewise.
(s7_build_dependency_insn_hsh, s7_insert_reg): Likewise.
* config/tc-sh.c (md_begin): Likewise.
* config/tc-sparc.c (md_begin): Likewise.
* config/tc-spu.c (md_begin): Likewise.
* config/tc-tic30.c (md_begin): Likewise.
* config/tc-tic4x.c (tic4x_inst_insert): Likewise.
* config/tc-tic54x.c (stag_add_field_symbols, md_begin): Likewise.
(tic54x_endstruct, tic54x_var, tic54x_macro_info): Likewise.
(subsym_substitute): Likewise.
* config/tc-tilegx.c (md_begin): Likewise.
* config/tc-tilepro.c (md_begin): Likewise.
* config/tc-vax.c (vip_begin): Likewise.
* config/tc-wasm32.c (md_begin): Likewise.
* config/tc-xgate.c (md_begin): Likewise.
* config/tc-z8k.c (md_begin): Likewise.
* testsuite/gas/ppc/dcbt.d,
* testsuite/gas/ppc/dcbt.s: New test.
* testsuite/gas/ppc/ppc.exp: Run it.
* ecoff.c (add_string): Report fatal error on duplicates.
* config/tc-alpha.c (md_begin): Likewise.
* config/tc-arc.c (arc_insert_opcode, declare_register): Likewise.
(declare_addrtype, md_begin, arc_extcorereg): Likewise.
* config/tc-cr16.c (initialise_reg_hash_table, md_begin): Likewise.
* config/tc-cris.c (md_begin): Likewise.
* config/tc-crx.c (md_begin): Likewise.
* config/tc-dlx.c (md_begin): Likewise.
* config/tc-hppa.c (md_begin): Likewise.
* config/tc-i386.c (md_begin): Likewise.
* config/tc-ia64.c (dot_rot, dot_entry, declare_register): Likewise.
(md_begin): Likewise.
* config/tc-m68k.c (md_begin): Likewise.
* config/tc-mips.c (md_begin): Likewise.
* config/tc-nios2.c (md_begin): Likewise.
* config/tc-ns32k.c (md_begin): Likewise.
* config/tc-ppc.c (ppc_setup_opcodes): Likewise.
* config/tc-pru.c (md_begin): Likewise.
* config/tc-riscv.c (init_ext_version_hash): Likewise.
(init_opcode_names_hash, hash_reg_name, init_opcode_hash): Likewise.
* config/tc-s390.c (s390_setup_opcodes, md_begin): Likewise.
* config/tc-sparc.c (md_begin): Likewise.
* config/tc-tic30.c (md_begin): Likewise.
* config/tc-tic4x.c (tic4x_inst_insert): Likewise.
* config/tc-tilegx.c (md_begin): Likewise.
* config/tc-tilepro.c (md_begin): Likewise.
* config/tc-vax.c (vip_begin): Likewise.
* config/tc-alpha.c,
* config/tc-arm.c,
* config/tc-avr.c,
* config/tc-cr16.c,
* config/tc-csky.c,
* config/tc-i386.c,
* config/tc-m68hc11.c,
* config/tc-m68k.c,
* config/tc-microblaze.c,
* config/tc-ns32k.c,
* config/tc-pj.c,
* config/tc-ppc.c,
* config/tc-score.c,
* config/tc-score7.c,
* config/tc-tic4x.c,
* config/tc-tic54x.c,
* config/tc-tilegx.c,
* config/tc-tilepro.c,
* config/tc-xgate.c: Formatting.
2020-08-22 16:29:57 +08:00
|
|
|
{
|
|
|
|
as_bad_where (macro->file, macro->line,
|
|
|
|
_("Reserved word `%s' used as parameter in macro `%s'"),
|
|
|
|
name, macro->name);
|
|
|
|
}
|
1999-05-03 15:29:11 +08:00
|
|
|
|
|
|
|
formal->index = NARG_INDEX;
|
|
|
|
*p = formal;
|
|
|
|
}
|
|
|
|
|
|
|
|
return idx;
|
|
|
|
}
|
|
|
|
|
2009-10-15 18:58:34 +08:00
|
|
|
/* Free the memory allocated to a macro. */
|
|
|
|
|
|
|
|
static void
|
|
|
|
free_macro (macro_entry *macro)
|
|
|
|
{
|
|
|
|
formal_entry *formal;
|
|
|
|
|
|
|
|
for (formal = macro->formals; formal; )
|
|
|
|
{
|
|
|
|
formal_entry *f;
|
|
|
|
|
|
|
|
f = formal;
|
|
|
|
formal = formal->next;
|
|
|
|
del_formal (f);
|
|
|
|
}
|
2020-08-16 01:47:01 +08:00
|
|
|
htab_delete (macro->formal_hash);
|
2009-10-15 18:58:34 +08:00
|
|
|
sb_kill (¯o->sub);
|
2023-01-27 08:01:56 +08:00
|
|
|
free ((char *) macro->name);
|
2009-10-15 18:58:34 +08:00
|
|
|
free (macro);
|
|
|
|
}
|
|
|
|
|
2023-01-27 08:01:56 +08:00
|
|
|
/* Define a new macro. */
|
1999-05-03 15:29:11 +08:00
|
|
|
|
2023-01-27 08:01:56 +08:00
|
|
|
macro_entry *
|
|
|
|
define_macro (sb *in, sb *label, size_t (*get_line) (sb *))
|
1999-05-03 15:29:11 +08:00
|
|
|
{
|
|
|
|
macro_entry *macro;
|
|
|
|
sb name;
|
2023-01-27 08:01:56 +08:00
|
|
|
size_t idx;
|
2005-04-25 14:43:46 +08:00
|
|
|
const char *error = NULL;
|
1999-05-03 15:29:11 +08:00
|
|
|
|
2016-04-01 21:26:30 +08:00
|
|
|
macro = XNEW (macro_entry);
|
1999-05-03 15:29:11 +08:00
|
|
|
sb_new (¯o->sub);
|
|
|
|
sb_new (&name);
|
2023-01-27 08:01:56 +08:00
|
|
|
macro->file = as_where (¯o->line);
|
1999-05-03 15:29:11 +08:00
|
|
|
|
|
|
|
macro->formal_count = 0;
|
|
|
|
macro->formals = 0;
|
macro.c: use string hash from hash.h for macro_hash
Another case of duplicated hash.h code, the only minor difference
being that macro->format_hash was created with 7 entries vs. str_hash
with 16 entries.
* macro.c (macro_init, define_macro): Use str_htab_create.
(do_formals, define_macro, macro_expand_body): Use str_hash_insert
(macro_expand_body): Use str_hash_find and str_hash_delete.
(delete_macro): Likewise.
(sub_actual, macro_expand, check_macro): Use str_hash_find.
(expand_irp): Use str_htab_create and str_hash_insert.
* macro.h (struct macro_struct): Tidy.
(struct macro_hash_entry, macro_hash_entry_t, hash_macro_entry),
(eq_macro_entry, macro_entry_alloc, macro_entry_find),
(struct formal_hash_entry, formal_hash_entry_t),
(hash_formal_entry, eq_formal_entry, formal_entry_alloc),
(formal_entry_find): Delete.
* config/tc-iq2000.c (iq2000_add_macro): Use str_htab_create
and str_hash_insert.
2022-07-07 07:07:10 +08:00
|
|
|
macro->formal_hash = str_htab_create ();
|
2024-05-13 16:56:09 +08:00
|
|
|
macro->count = 0;
|
1999-05-03 15:29:11 +08:00
|
|
|
|
2023-01-27 08:01:56 +08:00
|
|
|
idx = sb_skip_white (0, in);
|
1999-05-03 15:29:11 +08:00
|
|
|
if (! buffer_and_nest ("MACRO", "ENDM", ¯o->sub, get_line))
|
2005-04-25 14:43:46 +08:00
|
|
|
error = _("unexpected end of file in macro `%s' definition");
|
1999-05-03 15:29:11 +08:00
|
|
|
if (label != NULL && label->len != 0)
|
|
|
|
{
|
|
|
|
sb_add_sb (&name, label);
|
2005-04-25 14:43:46 +08:00
|
|
|
macro->name = sb_terminate (&name);
|
1999-05-03 15:29:11 +08:00
|
|
|
if (idx < in->len && in->ptr[idx] == '(')
|
|
|
|
{
|
2000-09-01 02:36:18 +08:00
|
|
|
/* It's the label: MACRO (formals,...) sort */
|
1999-05-03 15:29:11 +08:00
|
|
|
idx = do_formals (macro, idx + 1, in);
|
2005-04-25 14:43:46 +08:00
|
|
|
if (idx < in->len && in->ptr[idx] == ')')
|
|
|
|
idx = sb_skip_white (idx + 1, in);
|
|
|
|
else if (!error)
|
|
|
|
error = _("missing `)' after formals in macro definition `%s'");
|
1999-05-03 15:29:11 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2000-09-01 02:36:18 +08:00
|
|
|
/* It's the label: MACRO formals,... sort */
|
1999-05-03 15:29:11 +08:00
|
|
|
idx = do_formals (macro, idx, in);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
PR gas/14201
* sb.h (sb_max_power_two): Delete.
(struct sb): Delete "item" and "pot". Make "len" a size_t. Add "max".
(sb_element): Delete.
(sb_add_char, sb_add_buffer, sb_skip_comma, sb_skip_write): Update
prototypes.
* sb.c (string_count, free_list): Delete.
(sb_build, sb_kill, sb_check): Rewrite.
(scrub_from_sb, sb_add_char, sb_add_string, sb_add_buffer,
sb_skip_white, sb_skip_comma): Replace assorted int params,
vars and return types with size_t.
* input-scrub.c: Likewise.
* macro.c: Likewise.
* macro.h: Likewise.
* as.c: Likewise.
* as.h: Likewise.
* input-file.h: Likewise.
* input-file.c: Likewise.
* read.c: Likewise.
* app.c: ..or ptrdiff_t.
* input-file.c (input_file_get): Use ferror.
(input_file_give_next_buffer): Use input_file_get.
2012-06-07 20:47:23 +08:00
|
|
|
size_t cidx;
|
2005-01-31 22:26:13 +08:00
|
|
|
|
1999-05-03 15:29:11 +08:00
|
|
|
idx = get_token (idx, in, &name);
|
2005-04-25 14:43:46 +08:00
|
|
|
macro->name = sb_terminate (&name);
|
2005-01-31 22:26:13 +08:00
|
|
|
if (name.len == 0)
|
2005-04-25 14:43:46 +08:00
|
|
|
error = _("Missing macro name");
|
2005-01-31 22:26:13 +08:00
|
|
|
cidx = sb_skip_white (idx, in);
|
|
|
|
idx = sb_skip_comma (cidx, in);
|
|
|
|
if (idx == cidx || idx < in->len)
|
|
|
|
idx = do_formals (macro, idx, in);
|
|
|
|
else
|
|
|
|
idx = cidx;
|
1999-05-03 15:29:11 +08:00
|
|
|
}
|
2005-04-25 14:43:46 +08:00
|
|
|
if (!error && idx < in->len)
|
|
|
|
error = _("Bad parameter list for macro `%s'");
|
1999-05-03 15:29:11 +08:00
|
|
|
|
2000-09-01 02:36:18 +08:00
|
|
|
/* And stick it in the macro hash table. */
|
1999-05-03 15:29:11 +08:00
|
|
|
for (idx = 0; idx < name.len; idx++)
|
2001-09-19 13:33:36 +08:00
|
|
|
name.ptr[idx] = TOLOWER (name.ptr[idx]);
|
2005-04-25 14:43:46 +08:00
|
|
|
if (!error)
|
PR26513, 629310abec breaks assembling PowerPC Linux kernels
Inserting with replacement is wrong for some gas hash table uses.
This patch implements an htab_insert that conditionally replaces, and
similarly for str_hash_insert. str_hash_insert with replace=0 is
roughly equivalent to the older hash_insert, and str_hash_insert with
replace=1 to the older hash_jam, but return values are different. I
found it useful to know whether the slot was occupied prior to
inserting/replacing. I've also reinstated the fatal errors on messing
up opcode tables with duplicates.
PR 26513
* hash.h (htab_insert): Update prototype and comment.
(struct string_tuple): Make "value" a const void*.
(string_tuple_alloc): Likewise.
(str_hash_find, str_hash_find_n): Cast returned value.
(str_hash_insert): Add "replace" parameter, and return slot pointer.
Free alloc'd element when not inserted.
* hash.c (htab_insert): Likewise. Return slot when element exists,
otherwise return NULL.
* read.c (pop_insert): Insert into hash table without first searching.
* config/tc-avr.c (md_begin): Likewise.
* config/tc-msp430.c (md_begin): Likewise.
* config/tc-nds32.c (nds32_init_nds32_pseudo_opcodes): Likewise.
* config/tc-v850.c (md_begin): Likewise.
* macro.c (do_formals, define_macro, macro_expand_body): Likewise.
(delete_macro): Delete from hash table.
* config/tc-tic54x.c (subsym_create_or_replace): Correct logic.
* symbols.c (local_symbol_make, symbol_table_insert): Allow
replacement of hash table entries.
* config/obj-coff-seh.c (seh_hash_insert): Likewise.
* config/obj-coff.c (tag_insert): Likewise.
* config/tc-iq2000.c (iq2000_add_macro): Likewise.
* config/tc-m68k.c (md_begin): Likewise for aliases.
* config/tc-tic4x.c (tic4x_asg): Likewise.
* config/tc-tic6x.c (md_begin): Likewise.
* dw2gencfi.c (dwcfi_hash_find_or_make): Disallow replacement of
hash table entries.
* ecoff.c (add_string, get_tag): Likewise.
* macro.c (expand_irp): Likewise.
* config/obj-elf.c (build_additional_section_info): Likewise.
* config/tc-aarch64.c (insert_reg_alias): Likewise.
(checked_hash_insert): Likewise.
* config/tc-alpha.c (get_alpha_reloc_tag, md_begin): Likewise.
* config/tc-arc.c (arc_insert_opcode, declare_register): Likewise.
(declare_addrtype, md_begin, arc_extcorereg): Likewise.
* config/tc-arm.c (insert_reg_alias): Likewise.
(arm_tc_equal_in_insn, md_begin): Likewise.
* config/tc-cr16.c (initialise_reg_hash_table, md_begin): Likewise.
* config/tc-cris.c (md_begin): Likewise.
* config/tc-crx.c (md_begin): Likewise.
* config/tc-csky.c (md_begin): Likewise.
* config/tc-d10v.c (md_begin): Likewise.
* config/tc-dlx.c (md_begin): Likewise.
* config/tc-ft32.c (md_begin): Likewise.
* config/tc-h8300.c (md_begin): Likewise.
* config/tc-hppa.c (md_begin): Likewise.
* config/tc-i386.c (md_begin): Likewise.
* config/tc-ia64.c (dot_rot, dot_entry, declare_register): Likewise.
(md_begin, dot_alias): Likewise.
* config/tc-m68hc11.c (md_begin): Likewise.
* config/tc-m68k.c (md_begin): Likewise.
* config/tc-mcore.c (md_begin): Likewise.
* config/tc-microblaze.c (md_begin): Likewise.
* config/tc-mips.c (md_begin): Likewise.
* config/tc-mmix.c (md_begin): Likewise.
* config/tc-mn10200.c (md_begin): Likewise.
* config/tc-mn10300.c (md_begin): Likewise.
* config/tc-moxie.c (md_begin): Likewise.
* config/tc-nds32.c (nds32_relax_hint, md_begin): Likewise.
* config/tc-nios2.c (md_begin): Likewise.
* config/tc-ns32k.c (md_begin): Likewise.
* config/tc-pdp11.c (md_begin): Likewise.
* config/tc-pj.c (fake_opcode, md_begin): Likewise.
* config/tc-ppc.c (ppc_setup_opcodes): Likewise.
* config/tc-pru.c (md_begin): Likewise.
* config/tc-riscv.c (init_ext_version_hash): Likewise.
(init_opcode_names_hash, hash_reg_name, init_opcode_hash): Likewise.
(riscv_init_csr_hash): Likewise.
* config/tc-s390.c (s390_setup_opcodes, md_begin): Likewise.
* config/tc-score.c (s3_insert_reg): Likewise.
(s3_build_score_ops_hsh, s3_build_dependency_insn_hsh): Likewise.
* config/tc-score7.c (s7_build_score_ops_hsh): Likewise.
(s7_build_dependency_insn_hsh, s7_insert_reg): Likewise.
* config/tc-sh.c (md_begin): Likewise.
* config/tc-sparc.c (md_begin): Likewise.
* config/tc-spu.c (md_begin): Likewise.
* config/tc-tic30.c (md_begin): Likewise.
* config/tc-tic4x.c (tic4x_inst_insert): Likewise.
* config/tc-tic54x.c (stag_add_field_symbols, md_begin): Likewise.
(tic54x_endstruct, tic54x_var, tic54x_macro_info): Likewise.
(subsym_substitute): Likewise.
* config/tc-tilegx.c (md_begin): Likewise.
* config/tc-tilepro.c (md_begin): Likewise.
* config/tc-vax.c (vip_begin): Likewise.
* config/tc-wasm32.c (md_begin): Likewise.
* config/tc-xgate.c (md_begin): Likewise.
* config/tc-z8k.c (md_begin): Likewise.
* testsuite/gas/ppc/dcbt.d,
* testsuite/gas/ppc/dcbt.s: New test.
* testsuite/gas/ppc/ppc.exp: Run it.
* ecoff.c (add_string): Report fatal error on duplicates.
* config/tc-alpha.c (md_begin): Likewise.
* config/tc-arc.c (arc_insert_opcode, declare_register): Likewise.
(declare_addrtype, md_begin, arc_extcorereg): Likewise.
* config/tc-cr16.c (initialise_reg_hash_table, md_begin): Likewise.
* config/tc-cris.c (md_begin): Likewise.
* config/tc-crx.c (md_begin): Likewise.
* config/tc-dlx.c (md_begin): Likewise.
* config/tc-hppa.c (md_begin): Likewise.
* config/tc-i386.c (md_begin): Likewise.
* config/tc-ia64.c (dot_rot, dot_entry, declare_register): Likewise.
(md_begin): Likewise.
* config/tc-m68k.c (md_begin): Likewise.
* config/tc-mips.c (md_begin): Likewise.
* config/tc-nios2.c (md_begin): Likewise.
* config/tc-ns32k.c (md_begin): Likewise.
* config/tc-ppc.c (ppc_setup_opcodes): Likewise.
* config/tc-pru.c (md_begin): Likewise.
* config/tc-riscv.c (init_ext_version_hash): Likewise.
(init_opcode_names_hash, hash_reg_name, init_opcode_hash): Likewise.
* config/tc-s390.c (s390_setup_opcodes, md_begin): Likewise.
* config/tc-sparc.c (md_begin): Likewise.
* config/tc-tic30.c (md_begin): Likewise.
* config/tc-tic4x.c (tic4x_inst_insert): Likewise.
* config/tc-tilegx.c (md_begin): Likewise.
* config/tc-tilepro.c (md_begin): Likewise.
* config/tc-vax.c (vip_begin): Likewise.
* config/tc-alpha.c,
* config/tc-arm.c,
* config/tc-avr.c,
* config/tc-cr16.c,
* config/tc-csky.c,
* config/tc-i386.c,
* config/tc-m68hc11.c,
* config/tc-m68k.c,
* config/tc-microblaze.c,
* config/tc-ns32k.c,
* config/tc-pj.c,
* config/tc-ppc.c,
* config/tc-score.c,
* config/tc-score7.c,
* config/tc-tic4x.c,
* config/tc-tic54x.c,
* config/tc-tilegx.c,
* config/tc-tilepro.c,
* config/tc-xgate.c: Formatting.
2020-08-22 16:29:57 +08:00
|
|
|
{
|
macro.c: use string hash from hash.h for macro_hash
Another case of duplicated hash.h code, the only minor difference
being that macro->format_hash was created with 7 entries vs. str_hash
with 16 entries.
* macro.c (macro_init, define_macro): Use str_htab_create.
(do_formals, define_macro, macro_expand_body): Use str_hash_insert
(macro_expand_body): Use str_hash_find and str_hash_delete.
(delete_macro): Likewise.
(sub_actual, macro_expand, check_macro): Use str_hash_find.
(expand_irp): Use str_htab_create and str_hash_insert.
* macro.h (struct macro_struct): Tidy.
(struct macro_hash_entry, macro_hash_entry_t, hash_macro_entry),
(eq_macro_entry, macro_entry_alloc, macro_entry_find),
(struct formal_hash_entry, formal_hash_entry_t),
(hash_formal_entry, eq_formal_entry, formal_entry_alloc),
(formal_entry_find): Delete.
* config/tc-iq2000.c (iq2000_add_macro): Use str_htab_create
and str_hash_insert.
2022-07-07 07:07:10 +08:00
|
|
|
if (str_hash_insert (macro_hash, macro->name, macro, 0) != NULL)
|
|
|
|
error = _("Macro `%s' was already defined");
|
PR26513, 629310abec breaks assembling PowerPC Linux kernels
Inserting with replacement is wrong for some gas hash table uses.
This patch implements an htab_insert that conditionally replaces, and
similarly for str_hash_insert. str_hash_insert with replace=0 is
roughly equivalent to the older hash_insert, and str_hash_insert with
replace=1 to the older hash_jam, but return values are different. I
found it useful to know whether the slot was occupied prior to
inserting/replacing. I've also reinstated the fatal errors on messing
up opcode tables with duplicates.
PR 26513
* hash.h (htab_insert): Update prototype and comment.
(struct string_tuple): Make "value" a const void*.
(string_tuple_alloc): Likewise.
(str_hash_find, str_hash_find_n): Cast returned value.
(str_hash_insert): Add "replace" parameter, and return slot pointer.
Free alloc'd element when not inserted.
* hash.c (htab_insert): Likewise. Return slot when element exists,
otherwise return NULL.
* read.c (pop_insert): Insert into hash table without first searching.
* config/tc-avr.c (md_begin): Likewise.
* config/tc-msp430.c (md_begin): Likewise.
* config/tc-nds32.c (nds32_init_nds32_pseudo_opcodes): Likewise.
* config/tc-v850.c (md_begin): Likewise.
* macro.c (do_formals, define_macro, macro_expand_body): Likewise.
(delete_macro): Delete from hash table.
* config/tc-tic54x.c (subsym_create_or_replace): Correct logic.
* symbols.c (local_symbol_make, symbol_table_insert): Allow
replacement of hash table entries.
* config/obj-coff-seh.c (seh_hash_insert): Likewise.
* config/obj-coff.c (tag_insert): Likewise.
* config/tc-iq2000.c (iq2000_add_macro): Likewise.
* config/tc-m68k.c (md_begin): Likewise for aliases.
* config/tc-tic4x.c (tic4x_asg): Likewise.
* config/tc-tic6x.c (md_begin): Likewise.
* dw2gencfi.c (dwcfi_hash_find_or_make): Disallow replacement of
hash table entries.
* ecoff.c (add_string, get_tag): Likewise.
* macro.c (expand_irp): Likewise.
* config/obj-elf.c (build_additional_section_info): Likewise.
* config/tc-aarch64.c (insert_reg_alias): Likewise.
(checked_hash_insert): Likewise.
* config/tc-alpha.c (get_alpha_reloc_tag, md_begin): Likewise.
* config/tc-arc.c (arc_insert_opcode, declare_register): Likewise.
(declare_addrtype, md_begin, arc_extcorereg): Likewise.
* config/tc-arm.c (insert_reg_alias): Likewise.
(arm_tc_equal_in_insn, md_begin): Likewise.
* config/tc-cr16.c (initialise_reg_hash_table, md_begin): Likewise.
* config/tc-cris.c (md_begin): Likewise.
* config/tc-crx.c (md_begin): Likewise.
* config/tc-csky.c (md_begin): Likewise.
* config/tc-d10v.c (md_begin): Likewise.
* config/tc-dlx.c (md_begin): Likewise.
* config/tc-ft32.c (md_begin): Likewise.
* config/tc-h8300.c (md_begin): Likewise.
* config/tc-hppa.c (md_begin): Likewise.
* config/tc-i386.c (md_begin): Likewise.
* config/tc-ia64.c (dot_rot, dot_entry, declare_register): Likewise.
(md_begin, dot_alias): Likewise.
* config/tc-m68hc11.c (md_begin): Likewise.
* config/tc-m68k.c (md_begin): Likewise.
* config/tc-mcore.c (md_begin): Likewise.
* config/tc-microblaze.c (md_begin): Likewise.
* config/tc-mips.c (md_begin): Likewise.
* config/tc-mmix.c (md_begin): Likewise.
* config/tc-mn10200.c (md_begin): Likewise.
* config/tc-mn10300.c (md_begin): Likewise.
* config/tc-moxie.c (md_begin): Likewise.
* config/tc-nds32.c (nds32_relax_hint, md_begin): Likewise.
* config/tc-nios2.c (md_begin): Likewise.
* config/tc-ns32k.c (md_begin): Likewise.
* config/tc-pdp11.c (md_begin): Likewise.
* config/tc-pj.c (fake_opcode, md_begin): Likewise.
* config/tc-ppc.c (ppc_setup_opcodes): Likewise.
* config/tc-pru.c (md_begin): Likewise.
* config/tc-riscv.c (init_ext_version_hash): Likewise.
(init_opcode_names_hash, hash_reg_name, init_opcode_hash): Likewise.
(riscv_init_csr_hash): Likewise.
* config/tc-s390.c (s390_setup_opcodes, md_begin): Likewise.
* config/tc-score.c (s3_insert_reg): Likewise.
(s3_build_score_ops_hsh, s3_build_dependency_insn_hsh): Likewise.
* config/tc-score7.c (s7_build_score_ops_hsh): Likewise.
(s7_build_dependency_insn_hsh, s7_insert_reg): Likewise.
* config/tc-sh.c (md_begin): Likewise.
* config/tc-sparc.c (md_begin): Likewise.
* config/tc-spu.c (md_begin): Likewise.
* config/tc-tic30.c (md_begin): Likewise.
* config/tc-tic4x.c (tic4x_inst_insert): Likewise.
* config/tc-tic54x.c (stag_add_field_symbols, md_begin): Likewise.
(tic54x_endstruct, tic54x_var, tic54x_macro_info): Likewise.
(subsym_substitute): Likewise.
* config/tc-tilegx.c (md_begin): Likewise.
* config/tc-tilepro.c (md_begin): Likewise.
* config/tc-vax.c (vip_begin): Likewise.
* config/tc-wasm32.c (md_begin): Likewise.
* config/tc-xgate.c (md_begin): Likewise.
* config/tc-z8k.c (md_begin): Likewise.
* testsuite/gas/ppc/dcbt.d,
* testsuite/gas/ppc/dcbt.s: New test.
* testsuite/gas/ppc/ppc.exp: Run it.
* ecoff.c (add_string): Report fatal error on duplicates.
* config/tc-alpha.c (md_begin): Likewise.
* config/tc-arc.c (arc_insert_opcode, declare_register): Likewise.
(declare_addrtype, md_begin, arc_extcorereg): Likewise.
* config/tc-cr16.c (initialise_reg_hash_table, md_begin): Likewise.
* config/tc-cris.c (md_begin): Likewise.
* config/tc-crx.c (md_begin): Likewise.
* config/tc-dlx.c (md_begin): Likewise.
* config/tc-hppa.c (md_begin): Likewise.
* config/tc-i386.c (md_begin): Likewise.
* config/tc-ia64.c (dot_rot, dot_entry, declare_register): Likewise.
(md_begin): Likewise.
* config/tc-m68k.c (md_begin): Likewise.
* config/tc-mips.c (md_begin): Likewise.
* config/tc-nios2.c (md_begin): Likewise.
* config/tc-ns32k.c (md_begin): Likewise.
* config/tc-ppc.c (ppc_setup_opcodes): Likewise.
* config/tc-pru.c (md_begin): Likewise.
* config/tc-riscv.c (init_ext_version_hash): Likewise.
(init_opcode_names_hash, hash_reg_name, init_opcode_hash): Likewise.
* config/tc-s390.c (s390_setup_opcodes, md_begin): Likewise.
* config/tc-sparc.c (md_begin): Likewise.
* config/tc-tic30.c (md_begin): Likewise.
* config/tc-tic4x.c (tic4x_inst_insert): Likewise.
* config/tc-tilegx.c (md_begin): Likewise.
* config/tc-tilepro.c (md_begin): Likewise.
* config/tc-vax.c (vip_begin): Likewise.
* config/tc-alpha.c,
* config/tc-arm.c,
* config/tc-avr.c,
* config/tc-cr16.c,
* config/tc-csky.c,
* config/tc-i386.c,
* config/tc-m68hc11.c,
* config/tc-m68k.c,
* config/tc-microblaze.c,
* config/tc-ns32k.c,
* config/tc-pj.c,
* config/tc-ppc.c,
* config/tc-score.c,
* config/tc-score7.c,
* config/tc-tic4x.c,
* config/tc-tic54x.c,
* config/tc-tilegx.c,
* config/tc-tilepro.c,
* config/tc-xgate.c: Formatting.
2020-08-22 16:29:57 +08:00
|
|
|
}
|
1999-05-03 15:29:11 +08:00
|
|
|
|
2005-04-25 14:43:46 +08:00
|
|
|
if (!error)
|
|
|
|
macro_defined = 1;
|
|
|
|
else
|
2023-01-27 08:01:56 +08:00
|
|
|
{
|
|
|
|
as_bad_where (macro->file, macro->line, error, macro->name);
|
|
|
|
free_macro (macro);
|
|
|
|
macro = NULL;
|
|
|
|
}
|
1999-05-03 15:29:11 +08:00
|
|
|
|
2023-01-27 08:01:56 +08:00
|
|
|
return macro;
|
1999-05-03 15:29:11 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Scan a token, and then skip KIND. */
|
|
|
|
|
PR gas/14201
* sb.h (sb_max_power_two): Delete.
(struct sb): Delete "item" and "pot". Make "len" a size_t. Add "max".
(sb_element): Delete.
(sb_add_char, sb_add_buffer, sb_skip_comma, sb_skip_write): Update
prototypes.
* sb.c (string_count, free_list): Delete.
(sb_build, sb_kill, sb_check): Rewrite.
(scrub_from_sb, sb_add_char, sb_add_string, sb_add_buffer,
sb_skip_white, sb_skip_comma): Replace assorted int params,
vars and return types with size_t.
* input-scrub.c: Likewise.
* macro.c: Likewise.
* macro.h: Likewise.
* as.c: Likewise.
* as.h: Likewise.
* input-file.h: Likewise.
* input-file.c: Likewise.
* read.c: Likewise.
* app.c: ..or ptrdiff_t.
* input-file.c (input_file_get): Use ferror.
(input_file_give_next_buffer): Use input_file_get.
2012-06-07 20:47:23 +08:00
|
|
|
static size_t
|
|
|
|
get_apost_token (size_t idx, sb *in, sb *name, int kind)
|
1999-05-03 15:29:11 +08:00
|
|
|
{
|
|
|
|
idx = get_token (idx, in, name);
|
|
|
|
if (idx < in->len
|
|
|
|
&& in->ptr[idx] == kind
|
2023-03-17 17:05:57 +08:00
|
|
|
&& (! flag_mri || macro_strip_at)
|
1999-05-03 15:29:11 +08:00
|
|
|
&& (! macro_strip_at || kind == '@'))
|
|
|
|
idx++;
|
|
|
|
return idx;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Substitute the actual value for a formal parameter. */
|
|
|
|
|
PR gas/14201
* sb.h (sb_max_power_two): Delete.
(struct sb): Delete "item" and "pot". Make "len" a size_t. Add "max".
(sb_element): Delete.
(sb_add_char, sb_add_buffer, sb_skip_comma, sb_skip_write): Update
prototypes.
* sb.c (string_count, free_list): Delete.
(sb_build, sb_kill, sb_check): Rewrite.
(scrub_from_sb, sb_add_char, sb_add_string, sb_add_buffer,
sb_skip_white, sb_skip_comma): Replace assorted int params,
vars and return types with size_t.
* input-scrub.c: Likewise.
* macro.c: Likewise.
* macro.h: Likewise.
* as.c: Likewise.
* as.h: Likewise.
* input-file.h: Likewise.
* input-file.c: Likewise.
* read.c: Likewise.
* app.c: ..or ptrdiff_t.
* input-file.c (input_file_get): Use ferror.
(input_file_give_next_buffer): Use input_file_get.
2012-06-07 20:47:23 +08:00
|
|
|
static size_t
|
2020-08-16 01:47:01 +08:00
|
|
|
sub_actual (size_t start, sb *in, sb *t, struct htab *formal_hash,
|
2003-11-25 01:52:33 +08:00
|
|
|
int kind, sb *out, int copyifnotthere)
|
1999-05-03 15:29:11 +08:00
|
|
|
{
|
PR gas/14201
* sb.h (sb_max_power_two): Delete.
(struct sb): Delete "item" and "pot". Make "len" a size_t. Add "max".
(sb_element): Delete.
(sb_add_char, sb_add_buffer, sb_skip_comma, sb_skip_write): Update
prototypes.
* sb.c (string_count, free_list): Delete.
(sb_build, sb_kill, sb_check): Rewrite.
(scrub_from_sb, sb_add_char, sb_add_string, sb_add_buffer,
sb_skip_white, sb_skip_comma): Replace assorted int params,
vars and return types with size_t.
* input-scrub.c: Likewise.
* macro.c: Likewise.
* macro.h: Likewise.
* as.c: Likewise.
* as.h: Likewise.
* input-file.h: Likewise.
* input-file.c: Likewise.
* read.c: Likewise.
* app.c: ..or ptrdiff_t.
* input-file.c (input_file_get): Use ferror.
(input_file_give_next_buffer): Use input_file_get.
2012-06-07 20:47:23 +08:00
|
|
|
size_t src;
|
1999-05-03 15:29:11 +08:00
|
|
|
formal_entry *ptr;
|
|
|
|
|
|
|
|
src = get_apost_token (start, in, t, kind);
|
|
|
|
/* See if it's in the macro's hash table, unless this is
|
|
|
|
macro_strip_at and kind is '@' and the token did not end in '@'. */
|
|
|
|
if (macro_strip_at
|
|
|
|
&& kind == '@'
|
|
|
|
&& (src == start || in->ptr[src - 1] != '@'))
|
|
|
|
ptr = NULL;
|
|
|
|
else
|
macro.c: use string hash from hash.h for macro_hash
Another case of duplicated hash.h code, the only minor difference
being that macro->format_hash was created with 7 entries vs. str_hash
with 16 entries.
* macro.c (macro_init, define_macro): Use str_htab_create.
(do_formals, define_macro, macro_expand_body): Use str_hash_insert
(macro_expand_body): Use str_hash_find and str_hash_delete.
(delete_macro): Likewise.
(sub_actual, macro_expand, check_macro): Use str_hash_find.
(expand_irp): Use str_htab_create and str_hash_insert.
* macro.h (struct macro_struct): Tidy.
(struct macro_hash_entry, macro_hash_entry_t, hash_macro_entry),
(eq_macro_entry, macro_entry_alloc, macro_entry_find),
(struct formal_hash_entry, formal_hash_entry_t),
(hash_formal_entry, eq_formal_entry, formal_entry_alloc),
(formal_entry_find): Delete.
* config/tc-iq2000.c (iq2000_add_macro): Use str_htab_create
and str_hash_insert.
2022-07-07 07:07:10 +08:00
|
|
|
ptr = str_hash_find (formal_hash, sb_terminate (t));
|
1999-05-03 15:29:11 +08:00
|
|
|
if (ptr)
|
|
|
|
{
|
|
|
|
if (ptr->actual.len)
|
|
|
|
{
|
|
|
|
sb_add_sb (out, &ptr->actual);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sb_add_sb (out, &ptr->def);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (kind == '&')
|
|
|
|
{
|
|
|
|
/* Doing this permits people to use & in macro bodies. */
|
|
|
|
sb_add_char (out, '&');
|
2003-06-02 23:03:20 +08:00
|
|
|
sb_add_sb (out, t);
|
2010-08-18 13:56:41 +08:00
|
|
|
if (src != start && in->ptr[src - 1] == '&')
|
|
|
|
sb_add_char (out, '&');
|
1999-05-03 15:29:11 +08:00
|
|
|
}
|
|
|
|
else if (copyifnotthere)
|
|
|
|
{
|
|
|
|
sb_add_sb (out, t);
|
|
|
|
}
|
2000-09-01 02:36:18 +08:00
|
|
|
else
|
1999-05-03 15:29:11 +08:00
|
|
|
{
|
|
|
|
sb_add_char (out, '\\');
|
|
|
|
sb_add_sb (out, t);
|
|
|
|
}
|
|
|
|
return src;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Expand the body of a macro. */
|
|
|
|
|
|
|
|
static const char *
|
2003-11-25 01:52:33 +08:00
|
|
|
macro_expand_body (sb *in, sb *out, formal_entry *formals,
|
2024-05-24 18:23:22 +08:00
|
|
|
struct htab *formal_hash, const macro_entry *macro,
|
|
|
|
unsigned int instance)
|
1999-05-03 15:29:11 +08:00
|
|
|
{
|
|
|
|
sb t;
|
PR gas/14201
* sb.h (sb_max_power_two): Delete.
(struct sb): Delete "item" and "pot". Make "len" a size_t. Add "max".
(sb_element): Delete.
(sb_add_char, sb_add_buffer, sb_skip_comma, sb_skip_write): Update
prototypes.
* sb.c (string_count, free_list): Delete.
(sb_build, sb_kill, sb_check): Rewrite.
(scrub_from_sb, sb_add_char, sb_add_string, sb_add_buffer,
sb_skip_white, sb_skip_comma): Replace assorted int params,
vars and return types with size_t.
* input-scrub.c: Likewise.
* macro.c: Likewise.
* macro.h: Likewise.
* as.c: Likewise.
* as.h: Likewise.
* input-file.h: Likewise.
* input-file.c: Likewise.
* read.c: Likewise.
* app.c: ..or ptrdiff_t.
* input-file.c (input_file_get): Use ferror.
(input_file_give_next_buffer): Use input_file_get.
2012-06-07 20:47:23 +08:00
|
|
|
size_t src = 0;
|
|
|
|
int inquote = 0, macro_line = 0;
|
1999-05-03 15:29:11 +08:00
|
|
|
formal_entry *loclist = NULL;
|
2005-04-25 14:43:46 +08:00
|
|
|
const char *err = NULL;
|
1999-05-03 15:29:11 +08:00
|
|
|
|
|
|
|
sb_new (&t);
|
|
|
|
|
2005-04-25 14:43:46 +08:00
|
|
|
while (src < in->len && !err)
|
1999-05-03 15:29:11 +08:00
|
|
|
{
|
|
|
|
if (in->ptr[src] == '&')
|
|
|
|
{
|
|
|
|
sb_reset (&t);
|
2023-03-17 17:05:57 +08:00
|
|
|
if (flag_mri)
|
1999-05-03 15:29:11 +08:00
|
|
|
{
|
|
|
|
if (src + 1 < in->len && in->ptr[src + 1] == '&')
|
|
|
|
src = sub_actual (src + 2, in, &t, formal_hash, '\'', out, 1);
|
|
|
|
else
|
|
|
|
sb_add_char (out, in->ptr[src++]);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-01-23 23:23:07 +08:00
|
|
|
/* Permit macro parameter substitution delineated with
|
2010-08-18 13:56:41 +08:00
|
|
|
an '&' prefix and optional '&' suffix. */
|
1999-05-03 15:29:11 +08:00
|
|
|
src = sub_actual (src + 1, in, &t, formal_hash, '&', out, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (in->ptr[src] == '\\')
|
|
|
|
{
|
|
|
|
src++;
|
2005-04-11 20:46:38 +08:00
|
|
|
if (src < in->len && in->ptr[src] == '(')
|
1999-05-03 15:29:11 +08:00
|
|
|
{
|
2000-09-01 02:36:18 +08:00
|
|
|
/* Sub in till the next ')' literally. */
|
1999-05-03 15:29:11 +08:00
|
|
|
src++;
|
|
|
|
while (src < in->len && in->ptr[src] != ')')
|
|
|
|
{
|
|
|
|
sb_add_char (out, in->ptr[src++]);
|
|
|
|
}
|
2005-04-25 14:43:46 +08:00
|
|
|
if (src < in->len)
|
1999-05-03 15:29:11 +08:00
|
|
|
src++;
|
2005-04-25 14:43:46 +08:00
|
|
|
else if (!macro)
|
|
|
|
err = _("missing `)'");
|
1999-05-03 15:29:11 +08:00
|
|
|
else
|
2005-04-25 14:43:46 +08:00
|
|
|
as_bad_where (macro->file, macro->line + macro_line, _("missing `)'"));
|
1999-05-03 15:29:11 +08:00
|
|
|
}
|
2005-04-11 20:46:38 +08:00
|
|
|
else if (src < in->len && in->ptr[src] == '@')
|
1999-05-03 15:29:11 +08:00
|
|
|
{
|
2024-05-13 16:56:09 +08:00
|
|
|
/* Sub in the total macro invocation number. */
|
1999-05-03 15:29:11 +08:00
|
|
|
|
2016-07-01 19:35:01 +08:00
|
|
|
char buffer[12];
|
1999-05-03 15:29:11 +08:00
|
|
|
src++;
|
2024-05-13 16:56:09 +08:00
|
|
|
sprintf (buffer, "%u", macro_number);
|
|
|
|
sb_add_string (out, buffer);
|
|
|
|
}
|
2024-05-24 18:23:22 +08:00
|
|
|
else if (src < in->len && in->ptr[src] == '+')
|
2024-05-13 16:56:09 +08:00
|
|
|
{
|
|
|
|
/* Sub in the current macro invocation number. */
|
|
|
|
|
|
|
|
char buffer[12];
|
|
|
|
src++;
|
2024-05-24 18:23:22 +08:00
|
|
|
sprintf (buffer, "%d", instance);
|
1999-05-03 15:29:11 +08:00
|
|
|
sb_add_string (out, buffer);
|
|
|
|
}
|
2005-04-11 20:46:38 +08:00
|
|
|
else if (src < in->len && in->ptr[src] == '&')
|
1999-05-03 15:29:11 +08:00
|
|
|
{
|
|
|
|
/* This is a preprocessor variable name, we don't do them
|
2000-09-01 02:36:18 +08:00
|
|
|
here. */
|
1999-05-03 15:29:11 +08:00
|
|
|
sb_add_char (out, '\\');
|
|
|
|
sb_add_char (out, '&');
|
|
|
|
src++;
|
|
|
|
}
|
2023-03-17 17:05:57 +08:00
|
|
|
else if (flag_mri && src < in->len && ISALNUM (in->ptr[src]))
|
1999-05-03 15:29:11 +08:00
|
|
|
{
|
|
|
|
int ind;
|
|
|
|
formal_entry *f;
|
|
|
|
|
2001-09-19 13:33:36 +08:00
|
|
|
if (ISDIGIT (in->ptr[src]))
|
1999-05-03 15:29:11 +08:00
|
|
|
ind = in->ptr[src] - '0';
|
2001-09-19 13:33:36 +08:00
|
|
|
else if (ISUPPER (in->ptr[src]))
|
1999-05-03 15:29:11 +08:00
|
|
|
ind = in->ptr[src] - 'A' + 10;
|
|
|
|
else
|
|
|
|
ind = in->ptr[src] - 'a' + 10;
|
|
|
|
++src;
|
|
|
|
for (f = formals; f != NULL; f = f->next)
|
|
|
|
{
|
|
|
|
if (f->index == ind - 1)
|
|
|
|
{
|
|
|
|
if (f->actual.len != 0)
|
|
|
|
sb_add_sb (out, &f->actual);
|
|
|
|
else
|
|
|
|
sb_add_sb (out, &f->def);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sb_reset (&t);
|
|
|
|
src = sub_actual (src, in, &t, formal_hash, '\'', out, 0);
|
|
|
|
}
|
|
|
|
}
|
2023-03-17 17:06:18 +08:00
|
|
|
else if ((flag_macro_alternate || flag_mri)
|
2005-04-11 20:46:38 +08:00
|
|
|
&& is_name_beginner (in->ptr[src])
|
1999-05-03 15:29:11 +08:00
|
|
|
&& (! inquote
|
|
|
|
|| ! macro_strip_at
|
|
|
|
|| (src > 0 && in->ptr[src - 1] == '@')))
|
|
|
|
{
|
2005-04-25 14:43:46 +08:00
|
|
|
if (! macro
|
1999-05-03 15:29:11 +08:00
|
|
|
|| src + 5 >= in->len
|
|
|
|
|| strncasecmp (in->ptr + src, "LOCAL", 5) != 0
|
2010-04-20 23:54:48 +08:00
|
|
|
|| ! ISWHITE (in->ptr[src + 5])
|
|
|
|
/* PR 11507: Skip keyword LOCAL if it is found inside a quoted string. */
|
|
|
|
|| inquote)
|
1999-05-03 15:29:11 +08:00
|
|
|
{
|
|
|
|
sb_reset (&t);
|
|
|
|
src = sub_actual (src, in, &t, formal_hash,
|
|
|
|
(macro_strip_at && inquote) ? '@' : '\'',
|
|
|
|
out, 1);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
src = sb_skip_white (src + 5, in);
|
2002-12-02 23:42:15 +08:00
|
|
|
while (in->ptr[src] != '\n')
|
1999-05-03 15:29:11 +08:00
|
|
|
{
|
2005-04-25 14:43:46 +08:00
|
|
|
const char *name;
|
2005-05-06 14:50:31 +08:00
|
|
|
formal_entry *f = new_formal ();
|
1999-05-03 15:29:11 +08:00
|
|
|
|
|
|
|
src = get_token (src, in, &f->name);
|
2005-04-25 14:43:46 +08:00
|
|
|
name = sb_terminate (&f->name);
|
macro.c: use string hash from hash.h for macro_hash
Another case of duplicated hash.h code, the only minor difference
being that macro->format_hash was created with 7 entries vs. str_hash
with 16 entries.
* macro.c (macro_init, define_macro): Use str_htab_create.
(do_formals, define_macro, macro_expand_body): Use str_hash_insert
(macro_expand_body): Use str_hash_find and str_hash_delete.
(delete_macro): Likewise.
(sub_actual, macro_expand, check_macro): Use str_hash_find.
(expand_irp): Use str_htab_create and str_hash_insert.
* macro.h (struct macro_struct): Tidy.
(struct macro_hash_entry, macro_hash_entry_t, hash_macro_entry),
(eq_macro_entry, macro_entry_alloc, macro_entry_find),
(struct formal_hash_entry, formal_hash_entry_t),
(hash_formal_entry, eq_formal_entry, formal_entry_alloc),
(formal_entry_find): Delete.
* config/tc-iq2000.c (iq2000_add_macro): Use str_htab_create
and str_hash_insert.
2022-07-07 07:07:10 +08:00
|
|
|
if (str_hash_insert (formal_hash, name, f, 0) != NULL)
|
PR26513, 629310abec breaks assembling PowerPC Linux kernels
Inserting with replacement is wrong for some gas hash table uses.
This patch implements an htab_insert that conditionally replaces, and
similarly for str_hash_insert. str_hash_insert with replace=0 is
roughly equivalent to the older hash_insert, and str_hash_insert with
replace=1 to the older hash_jam, but return values are different. I
found it useful to know whether the slot was occupied prior to
inserting/replacing. I've also reinstated the fatal errors on messing
up opcode tables with duplicates.
PR 26513
* hash.h (htab_insert): Update prototype and comment.
(struct string_tuple): Make "value" a const void*.
(string_tuple_alloc): Likewise.
(str_hash_find, str_hash_find_n): Cast returned value.
(str_hash_insert): Add "replace" parameter, and return slot pointer.
Free alloc'd element when not inserted.
* hash.c (htab_insert): Likewise. Return slot when element exists,
otherwise return NULL.
* read.c (pop_insert): Insert into hash table without first searching.
* config/tc-avr.c (md_begin): Likewise.
* config/tc-msp430.c (md_begin): Likewise.
* config/tc-nds32.c (nds32_init_nds32_pseudo_opcodes): Likewise.
* config/tc-v850.c (md_begin): Likewise.
* macro.c (do_formals, define_macro, macro_expand_body): Likewise.
(delete_macro): Delete from hash table.
* config/tc-tic54x.c (subsym_create_or_replace): Correct logic.
* symbols.c (local_symbol_make, symbol_table_insert): Allow
replacement of hash table entries.
* config/obj-coff-seh.c (seh_hash_insert): Likewise.
* config/obj-coff.c (tag_insert): Likewise.
* config/tc-iq2000.c (iq2000_add_macro): Likewise.
* config/tc-m68k.c (md_begin): Likewise for aliases.
* config/tc-tic4x.c (tic4x_asg): Likewise.
* config/tc-tic6x.c (md_begin): Likewise.
* dw2gencfi.c (dwcfi_hash_find_or_make): Disallow replacement of
hash table entries.
* ecoff.c (add_string, get_tag): Likewise.
* macro.c (expand_irp): Likewise.
* config/obj-elf.c (build_additional_section_info): Likewise.
* config/tc-aarch64.c (insert_reg_alias): Likewise.
(checked_hash_insert): Likewise.
* config/tc-alpha.c (get_alpha_reloc_tag, md_begin): Likewise.
* config/tc-arc.c (arc_insert_opcode, declare_register): Likewise.
(declare_addrtype, md_begin, arc_extcorereg): Likewise.
* config/tc-arm.c (insert_reg_alias): Likewise.
(arm_tc_equal_in_insn, md_begin): Likewise.
* config/tc-cr16.c (initialise_reg_hash_table, md_begin): Likewise.
* config/tc-cris.c (md_begin): Likewise.
* config/tc-crx.c (md_begin): Likewise.
* config/tc-csky.c (md_begin): Likewise.
* config/tc-d10v.c (md_begin): Likewise.
* config/tc-dlx.c (md_begin): Likewise.
* config/tc-ft32.c (md_begin): Likewise.
* config/tc-h8300.c (md_begin): Likewise.
* config/tc-hppa.c (md_begin): Likewise.
* config/tc-i386.c (md_begin): Likewise.
* config/tc-ia64.c (dot_rot, dot_entry, declare_register): Likewise.
(md_begin, dot_alias): Likewise.
* config/tc-m68hc11.c (md_begin): Likewise.
* config/tc-m68k.c (md_begin): Likewise.
* config/tc-mcore.c (md_begin): Likewise.
* config/tc-microblaze.c (md_begin): Likewise.
* config/tc-mips.c (md_begin): Likewise.
* config/tc-mmix.c (md_begin): Likewise.
* config/tc-mn10200.c (md_begin): Likewise.
* config/tc-mn10300.c (md_begin): Likewise.
* config/tc-moxie.c (md_begin): Likewise.
* config/tc-nds32.c (nds32_relax_hint, md_begin): Likewise.
* config/tc-nios2.c (md_begin): Likewise.
* config/tc-ns32k.c (md_begin): Likewise.
* config/tc-pdp11.c (md_begin): Likewise.
* config/tc-pj.c (fake_opcode, md_begin): Likewise.
* config/tc-ppc.c (ppc_setup_opcodes): Likewise.
* config/tc-pru.c (md_begin): Likewise.
* config/tc-riscv.c (init_ext_version_hash): Likewise.
(init_opcode_names_hash, hash_reg_name, init_opcode_hash): Likewise.
(riscv_init_csr_hash): Likewise.
* config/tc-s390.c (s390_setup_opcodes, md_begin): Likewise.
* config/tc-score.c (s3_insert_reg): Likewise.
(s3_build_score_ops_hsh, s3_build_dependency_insn_hsh): Likewise.
* config/tc-score7.c (s7_build_score_ops_hsh): Likewise.
(s7_build_dependency_insn_hsh, s7_insert_reg): Likewise.
* config/tc-sh.c (md_begin): Likewise.
* config/tc-sparc.c (md_begin): Likewise.
* config/tc-spu.c (md_begin): Likewise.
* config/tc-tic30.c (md_begin): Likewise.
* config/tc-tic4x.c (tic4x_inst_insert): Likewise.
* config/tc-tic54x.c (stag_add_field_symbols, md_begin): Likewise.
(tic54x_endstruct, tic54x_var, tic54x_macro_info): Likewise.
(subsym_substitute): Likewise.
* config/tc-tilegx.c (md_begin): Likewise.
* config/tc-tilepro.c (md_begin): Likewise.
* config/tc-vax.c (vip_begin): Likewise.
* config/tc-wasm32.c (md_begin): Likewise.
* config/tc-xgate.c (md_begin): Likewise.
* config/tc-z8k.c (md_begin): Likewise.
* testsuite/gas/ppc/dcbt.d,
* testsuite/gas/ppc/dcbt.s: New test.
* testsuite/gas/ppc/ppc.exp: Run it.
* ecoff.c (add_string): Report fatal error on duplicates.
* config/tc-alpha.c (md_begin): Likewise.
* config/tc-arc.c (arc_insert_opcode, declare_register): Likewise.
(declare_addrtype, md_begin, arc_extcorereg): Likewise.
* config/tc-cr16.c (initialise_reg_hash_table, md_begin): Likewise.
* config/tc-cris.c (md_begin): Likewise.
* config/tc-crx.c (md_begin): Likewise.
* config/tc-dlx.c (md_begin): Likewise.
* config/tc-hppa.c (md_begin): Likewise.
* config/tc-i386.c (md_begin): Likewise.
* config/tc-ia64.c (dot_rot, dot_entry, declare_register): Likewise.
(md_begin): Likewise.
* config/tc-m68k.c (md_begin): Likewise.
* config/tc-mips.c (md_begin): Likewise.
* config/tc-nios2.c (md_begin): Likewise.
* config/tc-ns32k.c (md_begin): Likewise.
* config/tc-ppc.c (ppc_setup_opcodes): Likewise.
* config/tc-pru.c (md_begin): Likewise.
* config/tc-riscv.c (init_ext_version_hash): Likewise.
(init_opcode_names_hash, hash_reg_name, init_opcode_hash): Likewise.
* config/tc-s390.c (s390_setup_opcodes, md_begin): Likewise.
* config/tc-sparc.c (md_begin): Likewise.
* config/tc-tic30.c (md_begin): Likewise.
* config/tc-tic4x.c (tic4x_inst_insert): Likewise.
* config/tc-tilegx.c (md_begin): Likewise.
* config/tc-tilepro.c (md_begin): Likewise.
* config/tc-vax.c (vip_begin): Likewise.
* config/tc-alpha.c,
* config/tc-arm.c,
* config/tc-avr.c,
* config/tc-cr16.c,
* config/tc-csky.c,
* config/tc-i386.c,
* config/tc-m68hc11.c,
* config/tc-m68k.c,
* config/tc-microblaze.c,
* config/tc-ns32k.c,
* config/tc-pj.c,
* config/tc-ppc.c,
* config/tc-score.c,
* config/tc-score7.c,
* config/tc-tic4x.c,
* config/tc-tic54x.c,
* config/tc-tilegx.c,
* config/tc-tilepro.c,
* config/tc-xgate.c: Formatting.
2020-08-22 16:29:57 +08:00
|
|
|
{
|
|
|
|
as_bad_where (macro->file, macro->line + macro_line,
|
|
|
|
_("`%s' was already used as parameter "
|
|
|
|
"(or another local) name"), name);
|
|
|
|
del_formal (f);
|
|
|
|
}
|
|
|
|
else
|
2005-04-25 14:43:46 +08:00
|
|
|
{
|
|
|
|
static int loccnt;
|
|
|
|
char buf[20];
|
1999-05-03 15:29:11 +08:00
|
|
|
|
2005-04-25 14:43:46 +08:00
|
|
|
f->index = LOCAL_INDEX;
|
|
|
|
f->next = loclist;
|
|
|
|
loclist = f;
|
|
|
|
|
|
|
|
sprintf (buf, IS_ELF ? ".LL%04x" : "LL%04x", ++loccnt);
|
|
|
|
sb_add_string (&f->actual, buf);
|
|
|
|
}
|
1999-05-03 15:29:11 +08:00
|
|
|
|
|
|
|
src = sb_skip_comma (src, in);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (in->ptr[src] == '"'
|
2023-03-17 17:05:57 +08:00
|
|
|
|| (flag_mri && in->ptr[src] == '\''))
|
1999-05-03 15:29:11 +08:00
|
|
|
{
|
|
|
|
inquote = !inquote;
|
|
|
|
sb_add_char (out, in->ptr[src++]);
|
|
|
|
}
|
|
|
|
else if (in->ptr[src] == '@' && macro_strip_at)
|
|
|
|
{
|
|
|
|
++src;
|
|
|
|
if (src < in->len
|
|
|
|
&& in->ptr[src] == '@')
|
|
|
|
{
|
|
|
|
sb_add_char (out, '@');
|
|
|
|
++src;
|
|
|
|
}
|
|
|
|
}
|
2023-03-17 17:05:57 +08:00
|
|
|
else if (flag_mri
|
1999-05-03 15:29:11 +08:00
|
|
|
&& in->ptr[src] == '='
|
|
|
|
&& src + 1 < in->len
|
|
|
|
&& in->ptr[src + 1] == '=')
|
|
|
|
{
|
|
|
|
formal_entry *ptr;
|
|
|
|
|
|
|
|
sb_reset (&t);
|
|
|
|
src = get_token (src + 2, in, &t);
|
macro.c: use string hash from hash.h for macro_hash
Another case of duplicated hash.h code, the only minor difference
being that macro->format_hash was created with 7 entries vs. str_hash
with 16 entries.
* macro.c (macro_init, define_macro): Use str_htab_create.
(do_formals, define_macro, macro_expand_body): Use str_hash_insert
(macro_expand_body): Use str_hash_find and str_hash_delete.
(delete_macro): Likewise.
(sub_actual, macro_expand, check_macro): Use str_hash_find.
(expand_irp): Use str_htab_create and str_hash_insert.
* macro.h (struct macro_struct): Tidy.
(struct macro_hash_entry, macro_hash_entry_t, hash_macro_entry),
(eq_macro_entry, macro_entry_alloc, macro_entry_find),
(struct formal_hash_entry, formal_hash_entry_t),
(hash_formal_entry, eq_formal_entry, formal_entry_alloc),
(formal_entry_find): Delete.
* config/tc-iq2000.c (iq2000_add_macro): Use str_htab_create
and str_hash_insert.
2022-07-07 07:07:10 +08:00
|
|
|
ptr = str_hash_find (formal_hash, sb_terminate (&t));
|
1999-05-03 15:29:11 +08:00
|
|
|
if (ptr == NULL)
|
|
|
|
{
|
|
|
|
/* FIXME: We should really return a warning string here,
|
2013-01-11 01:11:17 +08:00
|
|
|
but we can't, because the == might be in the MRI
|
|
|
|
comment field, and, since the nature of the MRI
|
|
|
|
comment field depends upon the exact instruction
|
|
|
|
being used, we don't have enough information here to
|
|
|
|
figure out whether it is or not. Instead, we leave
|
|
|
|
the == in place, which should cause a syntax error if
|
|
|
|
it is not in a comment. */
|
1999-05-03 15:29:11 +08:00
|
|
|
sb_add_char (out, '=');
|
|
|
|
sb_add_char (out, '=');
|
|
|
|
sb_add_sb (out, &t);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (ptr->actual.len)
|
|
|
|
{
|
|
|
|
sb_add_string (out, "-1");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sb_add_char (out, '0');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2005-04-25 14:43:46 +08:00
|
|
|
if (in->ptr[src] == '\n')
|
|
|
|
++macro_line;
|
1999-05-03 15:29:11 +08:00
|
|
|
sb_add_char (out, in->ptr[src++]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sb_kill (&t);
|
|
|
|
|
|
|
|
while (loclist != NULL)
|
|
|
|
{
|
|
|
|
formal_entry *f;
|
2008-08-11 15:40:22 +08:00
|
|
|
const char *name;
|
1999-05-03 15:29:11 +08:00
|
|
|
|
|
|
|
f = loclist->next;
|
2008-08-11 15:40:22 +08:00
|
|
|
name = sb_terminate (&loclist->name);
|
macro.c: use string hash from hash.h for macro_hash
Another case of duplicated hash.h code, the only minor difference
being that macro->format_hash was created with 7 entries vs. str_hash
with 16 entries.
* macro.c (macro_init, define_macro): Use str_htab_create.
(do_formals, define_macro, macro_expand_body): Use str_hash_insert
(macro_expand_body): Use str_hash_find and str_hash_delete.
(delete_macro): Likewise.
(sub_actual, macro_expand, check_macro): Use str_hash_find.
(expand_irp): Use str_htab_create and str_hash_insert.
* macro.h (struct macro_struct): Tidy.
(struct macro_hash_entry, macro_hash_entry_t, hash_macro_entry),
(eq_macro_entry, macro_entry_alloc, macro_entry_find),
(struct formal_hash_entry, formal_hash_entry_t),
(hash_formal_entry, eq_formal_entry, formal_entry_alloc),
(formal_entry_find): Delete.
* config/tc-iq2000.c (iq2000_add_macro): Use str_htab_create
and str_hash_insert.
2022-07-07 07:07:10 +08:00
|
|
|
str_hash_delete (formal_hash, name);
|
2005-05-06 14:50:31 +08:00
|
|
|
del_formal (loclist);
|
1999-05-03 15:29:11 +08:00
|
|
|
loclist = f;
|
|
|
|
}
|
|
|
|
|
2022-08-11 08:21:03 +08:00
|
|
|
if (!err && (out->len == 0 || out->ptr[out->len - 1] != '\n'))
|
|
|
|
sb_add_char (out, '\n');
|
2005-04-25 14:43:46 +08:00
|
|
|
return err;
|
1999-05-03 15:29:11 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Assign values to the formal parameters of a macro, and expand the
|
|
|
|
body. */
|
|
|
|
|
|
|
|
static const char *
|
PR gas/14201
* sb.h (sb_max_power_two): Delete.
(struct sb): Delete "item" and "pot". Make "len" a size_t. Add "max".
(sb_element): Delete.
(sb_add_char, sb_add_buffer, sb_skip_comma, sb_skip_write): Update
prototypes.
* sb.c (string_count, free_list): Delete.
(sb_build, sb_kill, sb_check): Rewrite.
(scrub_from_sb, sb_add_char, sb_add_string, sb_add_buffer,
sb_skip_white, sb_skip_comma): Replace assorted int params,
vars and return types with size_t.
* input-scrub.c: Likewise.
* macro.c: Likewise.
* macro.h: Likewise.
* as.c: Likewise.
* as.h: Likewise.
* input-file.h: Likewise.
* input-file.c: Likewise.
* read.c: Likewise.
* app.c: ..or ptrdiff_t.
* input-file.c (input_file_get): Use ferror.
(input_file_give_next_buffer): Use input_file_get.
2012-06-07 20:47:23 +08:00
|
|
|
macro_expand (size_t idx, sb *in, macro_entry *m, sb *out)
|
1999-05-03 15:29:11 +08:00
|
|
|
{
|
|
|
|
sb t;
|
|
|
|
formal_entry *ptr;
|
|
|
|
formal_entry *f;
|
|
|
|
int is_keyword = 0;
|
|
|
|
int narg = 0;
|
2005-05-06 14:50:31 +08:00
|
|
|
const char *err = NULL;
|
1999-05-03 15:29:11 +08:00
|
|
|
|
|
|
|
sb_new (&t);
|
2000-09-01 02:36:18 +08:00
|
|
|
|
|
|
|
/* Reset any old value the actuals may have. */
|
1999-05-03 15:29:11 +08:00
|
|
|
for (f = m->formals; f; f = f->next)
|
2000-09-01 02:36:18 +08:00
|
|
|
sb_reset (&f->actual);
|
1999-05-03 15:29:11 +08:00
|
|
|
f = m->formals;
|
|
|
|
while (f != NULL && f->index < 0)
|
|
|
|
f = f->next;
|
|
|
|
|
2023-03-17 17:05:57 +08:00
|
|
|
if (flag_mri)
|
1999-05-03 15:29:11 +08:00
|
|
|
{
|
|
|
|
/* The macro may be called with an optional qualifier, which may
|
2013-01-11 01:11:17 +08:00
|
|
|
be referred to in the macro body as \0. */
|
1999-05-03 15:29:11 +08:00
|
|
|
if (idx < in->len && in->ptr[idx] == '.')
|
2002-05-03 10:25:33 +08:00
|
|
|
{
|
|
|
|
/* The Microtec assembler ignores this if followed by a white space.
|
|
|
|
(Macro invocation with empty extension) */
|
|
|
|
idx++;
|
|
|
|
if ( idx < in->len
|
|
|
|
&& in->ptr[idx] != ' '
|
|
|
|
&& in->ptr[idx] != '\t')
|
|
|
|
{
|
2005-05-06 14:50:31 +08:00
|
|
|
formal_entry *n = new_formal ();
|
2002-05-03 10:25:33 +08:00
|
|
|
|
|
|
|
n->index = QUAL_INDEX;
|
|
|
|
|
|
|
|
n->next = m->formals;
|
|
|
|
m->formals = n;
|
|
|
|
|
2005-05-10 15:48:24 +08:00
|
|
|
idx = get_any_string (idx, in, &n->actual);
|
2002-05-03 10:25:33 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
1999-05-03 15:29:11 +08:00
|
|
|
|
2000-09-01 02:36:18 +08:00
|
|
|
/* Peel off the actuals and store them away in the hash tables' actuals. */
|
1999-05-03 15:29:11 +08:00
|
|
|
idx = sb_skip_white (idx, in);
|
2002-12-02 23:42:15 +08:00
|
|
|
while (idx < in->len)
|
1999-05-03 15:29:11 +08:00
|
|
|
{
|
PR gas/14201
* sb.h (sb_max_power_two): Delete.
(struct sb): Delete "item" and "pot". Make "len" a size_t. Add "max".
(sb_element): Delete.
(sb_add_char, sb_add_buffer, sb_skip_comma, sb_skip_write): Update
prototypes.
* sb.c (string_count, free_list): Delete.
(sb_build, sb_kill, sb_check): Rewrite.
(scrub_from_sb, sb_add_char, sb_add_string, sb_add_buffer,
sb_skip_white, sb_skip_comma): Replace assorted int params,
vars and return types with size_t.
* input-scrub.c: Likewise.
* macro.c: Likewise.
* macro.h: Likewise.
* as.c: Likewise.
* as.h: Likewise.
* input-file.h: Likewise.
* input-file.c: Likewise.
* read.c: Likewise.
* app.c: ..or ptrdiff_t.
* input-file.c (input_file_get): Use ferror.
(input_file_give_next_buffer): Use input_file_get.
2012-06-07 20:47:23 +08:00
|
|
|
size_t scan;
|
1999-05-03 15:29:11 +08:00
|
|
|
|
2000-09-01 02:36:18 +08:00
|
|
|
/* Look and see if it's a positional or keyword arg. */
|
1999-05-03 15:29:11 +08:00
|
|
|
scan = idx;
|
|
|
|
while (scan < in->len
|
|
|
|
&& !ISSEP (in->ptr[scan])
|
2023-03-17 17:05:57 +08:00
|
|
|
&& !(flag_mri && in->ptr[scan] == '\'')
|
2023-03-17 17:06:18 +08:00
|
|
|
&& (!flag_macro_alternate && in->ptr[scan] != '='))
|
1999-05-03 15:29:11 +08:00
|
|
|
scan++;
|
2023-03-17 17:06:18 +08:00
|
|
|
if (scan < in->len && !flag_macro_alternate && in->ptr[scan] == '=')
|
1999-05-03 15:29:11 +08:00
|
|
|
{
|
|
|
|
is_keyword = 1;
|
|
|
|
|
|
|
|
/* It's OK to go from positional to keyword. */
|
|
|
|
|
|
|
|
/* This is a keyword arg, fetch the formal name and
|
2000-09-01 02:36:18 +08:00
|
|
|
then the actual stuff. */
|
1999-05-03 15:29:11 +08:00
|
|
|
sb_reset (&t);
|
|
|
|
idx = get_token (idx, in, &t);
|
2023-03-02 05:42:00 +08:00
|
|
|
if (idx >= in->len || in->ptr[idx] != '=')
|
2005-05-06 14:50:31 +08:00
|
|
|
{
|
|
|
|
err = _("confusion in formal parameters");
|
|
|
|
break;
|
|
|
|
}
|
1999-05-03 15:29:11 +08:00
|
|
|
|
2000-09-01 02:36:18 +08:00
|
|
|
/* Lookup the formal in the macro's list. */
|
macro.c: use string hash from hash.h for macro_hash
Another case of duplicated hash.h code, the only minor difference
being that macro->format_hash was created with 7 entries vs. str_hash
with 16 entries.
* macro.c (macro_init, define_macro): Use str_htab_create.
(do_formals, define_macro, macro_expand_body): Use str_hash_insert
(macro_expand_body): Use str_hash_find and str_hash_delete.
(delete_macro): Likewise.
(sub_actual, macro_expand, check_macro): Use str_hash_find.
(expand_irp): Use str_htab_create and str_hash_insert.
* macro.h (struct macro_struct): Tidy.
(struct macro_hash_entry, macro_hash_entry_t, hash_macro_entry),
(eq_macro_entry, macro_entry_alloc, macro_entry_find),
(struct formal_hash_entry, formal_hash_entry_t),
(hash_formal_entry, eq_formal_entry, formal_entry_alloc),
(formal_entry_find): Delete.
* config/tc-iq2000.c (iq2000_add_macro): Use str_htab_create
and str_hash_insert.
2022-07-07 07:07:10 +08:00
|
|
|
ptr = str_hash_find (m->formal_hash, sb_terminate (&t));
|
1999-05-03 15:29:11 +08:00
|
|
|
if (!ptr)
|
2010-07-23 14:44:25 +08:00
|
|
|
{
|
|
|
|
as_bad (_("Parameter named `%s' does not exist for macro `%s'"),
|
|
|
|
t.ptr,
|
|
|
|
m->name);
|
|
|
|
sb_reset (&t);
|
|
|
|
idx = get_any_string (idx + 1, in, &t);
|
|
|
|
}
|
1999-05-03 15:29:11 +08:00
|
|
|
else
|
|
|
|
{
|
2000-09-01 02:36:18 +08:00
|
|
|
/* Insert this value into the right place. */
|
2005-05-06 14:50:31 +08:00
|
|
|
if (ptr->actual.len)
|
|
|
|
{
|
|
|
|
as_warn (_("Value for parameter `%s' of macro `%s' was already specified"),
|
|
|
|
ptr->name.ptr,
|
|
|
|
m->name);
|
|
|
|
sb_reset (&ptr->actual);
|
|
|
|
}
|
2005-05-10 15:48:24 +08:00
|
|
|
idx = get_any_string (idx + 1, in, &ptr->actual);
|
1999-05-03 15:29:11 +08:00
|
|
|
if (ptr->actual.len > 0)
|
|
|
|
++narg;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (is_keyword)
|
2005-05-06 14:50:31 +08:00
|
|
|
{
|
|
|
|
err = _("can't mix positional and keyword arguments");
|
|
|
|
break;
|
|
|
|
}
|
1999-05-03 15:29:11 +08:00
|
|
|
|
|
|
|
if (!f)
|
|
|
|
{
|
|
|
|
formal_entry **pf;
|
|
|
|
int c;
|
|
|
|
|
2023-03-17 17:05:57 +08:00
|
|
|
if (!flag_mri)
|
2005-05-06 14:50:31 +08:00
|
|
|
{
|
|
|
|
err = _("too many positional arguments");
|
|
|
|
break;
|
|
|
|
}
|
1999-05-03 15:29:11 +08:00
|
|
|
|
2005-05-06 14:50:31 +08:00
|
|
|
f = new_formal ();
|
1999-05-03 15:29:11 +08:00
|
|
|
|
|
|
|
c = -1;
|
|
|
|
for (pf = &m->formals; *pf != NULL; pf = &(*pf)->next)
|
|
|
|
if ((*pf)->index >= c)
|
|
|
|
c = (*pf)->index + 1;
|
|
|
|
if (c == -1)
|
|
|
|
c = 0;
|
|
|
|
*pf = f;
|
|
|
|
f->index = c;
|
|
|
|
}
|
|
|
|
|
2005-05-06 14:50:31 +08:00
|
|
|
if (f->type != FORMAL_VARARG)
|
2005-05-10 15:48:24 +08:00
|
|
|
idx = get_any_string (idx, in, &f->actual);
|
2023-03-02 05:42:00 +08:00
|
|
|
else if (idx < in->len)
|
2005-05-06 14:50:31 +08:00
|
|
|
{
|
|
|
|
sb_add_buffer (&f->actual, in->ptr + idx, in->len - idx);
|
|
|
|
idx = in->len;
|
|
|
|
}
|
1999-05-03 15:29:11 +08:00
|
|
|
if (f->actual.len > 0)
|
|
|
|
++narg;
|
|
|
|
do
|
|
|
|
{
|
|
|
|
f = f->next;
|
|
|
|
}
|
|
|
|
while (f != NULL && f->index < 0);
|
|
|
|
}
|
|
|
|
|
2023-03-17 17:05:57 +08:00
|
|
|
if (! flag_mri)
|
1999-05-03 15:29:11 +08:00
|
|
|
idx = sb_skip_comma (idx, in);
|
|
|
|
else
|
|
|
|
{
|
2023-03-02 05:42:00 +08:00
|
|
|
if (idx < in->len && in->ptr[idx] == ',')
|
1999-05-03 15:29:11 +08:00
|
|
|
++idx;
|
2023-03-02 05:42:00 +08:00
|
|
|
if (idx < in->len && ISWHITE (in->ptr[idx]))
|
1999-05-03 15:29:11 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-05-06 14:50:31 +08:00
|
|
|
if (! err)
|
1999-05-03 15:29:11 +08:00
|
|
|
{
|
2005-05-06 14:50:31 +08:00
|
|
|
for (ptr = m->formals; ptr; ptr = ptr->next)
|
|
|
|
{
|
|
|
|
if (ptr->type == FORMAL_REQUIRED && ptr->actual.len == 0)
|
|
|
|
as_bad (_("Missing value for required parameter `%s' of macro `%s'"),
|
|
|
|
ptr->name.ptr,
|
|
|
|
m->name);
|
|
|
|
}
|
1999-05-03 15:29:11 +08:00
|
|
|
|
2023-03-17 17:05:57 +08:00
|
|
|
if (flag_mri)
|
2005-05-06 14:50:31 +08:00
|
|
|
{
|
2023-03-02 05:04:40 +08:00
|
|
|
ptr = str_hash_find (m->formal_hash,
|
|
|
|
macro_strip_at ? "$NARG" : "NARG");
|
|
|
|
if (ptr)
|
|
|
|
{
|
|
|
|
char buffer[20];
|
|
|
|
sprintf (buffer, "%d", narg);
|
|
|
|
sb_add_string (&ptr->actual, buffer);
|
|
|
|
}
|
2005-05-06 14:50:31 +08:00
|
|
|
}
|
|
|
|
|
2024-05-24 18:23:22 +08:00
|
|
|
err = macro_expand_body (&m->sub, out, m->formals, m->formal_hash, m,
|
|
|
|
m->count);
|
2005-05-06 14:50:31 +08:00
|
|
|
}
|
1999-05-03 15:29:11 +08:00
|
|
|
|
|
|
|
/* Discard any unnamed formal arguments. */
|
2023-03-17 17:05:57 +08:00
|
|
|
if (flag_mri)
|
1999-05-03 15:29:11 +08:00
|
|
|
{
|
|
|
|
formal_entry **pf;
|
|
|
|
|
|
|
|
pf = &m->formals;
|
|
|
|
while (*pf != NULL)
|
|
|
|
{
|
|
|
|
if ((*pf)->name.len != 0)
|
|
|
|
pf = &(*pf)->next;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
f = (*pf)->next;
|
2005-05-06 14:50:31 +08:00
|
|
|
del_formal (*pf);
|
1999-05-03 15:29:11 +08:00
|
|
|
*pf = f;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sb_kill (&t);
|
2005-04-25 14:43:46 +08:00
|
|
|
if (!err)
|
2024-05-13 16:56:09 +08:00
|
|
|
{
|
|
|
|
macro_number++;
|
|
|
|
m->count++;
|
|
|
|
}
|
1999-05-03 15:29:11 +08:00
|
|
|
|
2005-04-25 14:43:46 +08:00
|
|
|
return err;
|
1999-05-03 15:29:11 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Check for a macro. If one is found, put the expansion into
|
2002-12-02 23:42:15 +08:00
|
|
|
*EXPAND. Return 1 if a macro is found, 0 otherwise. */
|
1999-05-03 15:29:11 +08:00
|
|
|
|
|
|
|
int
|
2003-11-25 01:52:33 +08:00
|
|
|
check_macro (const char *line, sb *expand,
|
|
|
|
const char **error, macro_entry **info)
|
1999-05-03 15:29:11 +08:00
|
|
|
{
|
|
|
|
const char *s;
|
2009-12-11 21:42:17 +08:00
|
|
|
char *copy, *cls;
|
1999-05-03 15:29:11 +08:00
|
|
|
macro_entry *macro;
|
|
|
|
sb line_sb;
|
|
|
|
|
2005-04-11 20:46:38 +08:00
|
|
|
if (! is_name_beginner (*line)
|
2023-03-17 17:05:57 +08:00
|
|
|
&& (! flag_mri || *line != '.'))
|
1999-05-03 15:29:11 +08:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
s = line + 1;
|
2005-04-11 20:46:38 +08:00
|
|
|
while (is_part_of_name (*s))
|
|
|
|
++s;
|
|
|
|
if (is_name_ender (*s))
|
1999-05-03 15:29:11 +08:00
|
|
|
++s;
|
|
|
|
|
2016-03-28 17:49:15 +08:00
|
|
|
copy = xmemdup0 (line, s - line);
|
2009-12-11 21:42:17 +08:00
|
|
|
for (cls = copy; *cls != '\0'; cls ++)
|
|
|
|
*cls = TOLOWER (*cls);
|
1999-05-03 15:29:11 +08:00
|
|
|
|
macro.c: use string hash from hash.h for macro_hash
Another case of duplicated hash.h code, the only minor difference
being that macro->format_hash was created with 7 entries vs. str_hash
with 16 entries.
* macro.c (macro_init, define_macro): Use str_htab_create.
(do_formals, define_macro, macro_expand_body): Use str_hash_insert
(macro_expand_body): Use str_hash_find and str_hash_delete.
(delete_macro): Likewise.
(sub_actual, macro_expand, check_macro): Use str_hash_find.
(expand_irp): Use str_htab_create and str_hash_insert.
* macro.h (struct macro_struct): Tidy.
(struct macro_hash_entry, macro_hash_entry_t, hash_macro_entry),
(eq_macro_entry, macro_entry_alloc, macro_entry_find),
(struct formal_hash_entry, formal_hash_entry_t),
(hash_formal_entry, eq_formal_entry, formal_entry_alloc),
(formal_entry_find): Delete.
* config/tc-iq2000.c (iq2000_add_macro): Use str_htab_create
and str_hash_insert.
2022-07-07 07:07:10 +08:00
|
|
|
macro = str_hash_find (macro_hash, copy);
|
2016-03-22 00:31:46 +08:00
|
|
|
free (copy);
|
1999-05-03 15:29:11 +08:00
|
|
|
|
|
|
|
if (macro == NULL)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/* Wrap the line up in an sb. */
|
|
|
|
sb_new (&line_sb);
|
|
|
|
while (*s != '\0' && *s != '\n' && *s != '\r')
|
|
|
|
sb_add_char (&line_sb, *s++);
|
|
|
|
|
|
|
|
sb_new (expand);
|
2002-12-02 23:42:15 +08:00
|
|
|
*error = macro_expand (0, &line_sb, macro, expand);
|
1999-05-03 15:29:11 +08:00
|
|
|
|
|
|
|
sb_kill (&line_sb);
|
|
|
|
|
2000-09-01 02:36:18 +08:00
|
|
|
/* Export the macro information if requested. */
|
2000-03-26 22:47:33 +08:00
|
|
|
if (info)
|
|
|
|
*info = macro;
|
|
|
|
|
1999-05-03 15:29:11 +08:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Delete a macro. */
|
|
|
|
|
|
|
|
void
|
2003-11-25 01:52:33 +08:00
|
|
|
delete_macro (const char *name)
|
1999-05-03 15:29:11 +08:00
|
|
|
{
|
2005-04-18 21:35:46 +08:00
|
|
|
char *copy;
|
|
|
|
size_t i, len;
|
macro.c: use string hash from hash.h for macro_hash
Another case of duplicated hash.h code, the only minor difference
being that macro->format_hash was created with 7 entries vs. str_hash
with 16 entries.
* macro.c (macro_init, define_macro): Use str_htab_create.
(do_formals, define_macro, macro_expand_body): Use str_hash_insert
(macro_expand_body): Use str_hash_find and str_hash_delete.
(delete_macro): Likewise.
(sub_actual, macro_expand, check_macro): Use str_hash_find.
(expand_irp): Use str_htab_create and str_hash_insert.
* macro.h (struct macro_struct): Tidy.
(struct macro_hash_entry, macro_hash_entry_t, hash_macro_entry),
(eq_macro_entry, macro_entry_alloc, macro_entry_find),
(struct formal_hash_entry, formal_hash_entry_t),
(hash_formal_entry, eq_formal_entry, formal_entry_alloc),
(formal_entry_find): Delete.
* config/tc-iq2000.c (iq2000_add_macro): Use str_htab_create
and str_hash_insert.
2022-07-07 07:07:10 +08:00
|
|
|
macro_entry *macro;
|
2005-04-18 21:35:46 +08:00
|
|
|
|
|
|
|
len = strlen (name);
|
2016-04-07 04:26:46 +08:00
|
|
|
copy = XNEWVEC (char, len + 1);
|
2005-04-18 21:35:46 +08:00
|
|
|
for (i = 0; i < len; ++i)
|
|
|
|
copy[i] = TOLOWER (name[i]);
|
|
|
|
copy[i] = '\0';
|
|
|
|
|
macro.c: use string hash from hash.h for macro_hash
Another case of duplicated hash.h code, the only minor difference
being that macro->format_hash was created with 7 entries vs. str_hash
with 16 entries.
* macro.c (macro_init, define_macro): Use str_htab_create.
(do_formals, define_macro, macro_expand_body): Use str_hash_insert
(macro_expand_body): Use str_hash_find and str_hash_delete.
(delete_macro): Likewise.
(sub_actual, macro_expand, check_macro): Use str_hash_find.
(expand_irp): Use str_htab_create and str_hash_insert.
* macro.h (struct macro_struct): Tidy.
(struct macro_hash_entry, macro_hash_entry_t, hash_macro_entry),
(eq_macro_entry, macro_entry_alloc, macro_entry_find),
(struct formal_hash_entry, formal_hash_entry_t),
(hash_formal_entry, eq_formal_entry, formal_entry_alloc),
(formal_entry_find): Delete.
* config/tc-iq2000.c (iq2000_add_macro): Use str_htab_create
and str_hash_insert.
2022-07-07 07:07:10 +08:00
|
|
|
macro = str_hash_find (macro_hash, copy);
|
|
|
|
if (macro != NULL)
|
2023-01-27 08:01:56 +08:00
|
|
|
str_hash_delete (macro_hash, copy);
|
2005-04-18 21:35:46 +08:00
|
|
|
else
|
2017-01-23 23:23:07 +08:00
|
|
|
as_warn (_("Attempt to purge non-existing macro `%s'"), copy);
|
PR26513, 629310abec breaks assembling PowerPC Linux kernels
Inserting with replacement is wrong for some gas hash table uses.
This patch implements an htab_insert that conditionally replaces, and
similarly for str_hash_insert. str_hash_insert with replace=0 is
roughly equivalent to the older hash_insert, and str_hash_insert with
replace=1 to the older hash_jam, but return values are different. I
found it useful to know whether the slot was occupied prior to
inserting/replacing. I've also reinstated the fatal errors on messing
up opcode tables with duplicates.
PR 26513
* hash.h (htab_insert): Update prototype and comment.
(struct string_tuple): Make "value" a const void*.
(string_tuple_alloc): Likewise.
(str_hash_find, str_hash_find_n): Cast returned value.
(str_hash_insert): Add "replace" parameter, and return slot pointer.
Free alloc'd element when not inserted.
* hash.c (htab_insert): Likewise. Return slot when element exists,
otherwise return NULL.
* read.c (pop_insert): Insert into hash table without first searching.
* config/tc-avr.c (md_begin): Likewise.
* config/tc-msp430.c (md_begin): Likewise.
* config/tc-nds32.c (nds32_init_nds32_pseudo_opcodes): Likewise.
* config/tc-v850.c (md_begin): Likewise.
* macro.c (do_formals, define_macro, macro_expand_body): Likewise.
(delete_macro): Delete from hash table.
* config/tc-tic54x.c (subsym_create_or_replace): Correct logic.
* symbols.c (local_symbol_make, symbol_table_insert): Allow
replacement of hash table entries.
* config/obj-coff-seh.c (seh_hash_insert): Likewise.
* config/obj-coff.c (tag_insert): Likewise.
* config/tc-iq2000.c (iq2000_add_macro): Likewise.
* config/tc-m68k.c (md_begin): Likewise for aliases.
* config/tc-tic4x.c (tic4x_asg): Likewise.
* config/tc-tic6x.c (md_begin): Likewise.
* dw2gencfi.c (dwcfi_hash_find_or_make): Disallow replacement of
hash table entries.
* ecoff.c (add_string, get_tag): Likewise.
* macro.c (expand_irp): Likewise.
* config/obj-elf.c (build_additional_section_info): Likewise.
* config/tc-aarch64.c (insert_reg_alias): Likewise.
(checked_hash_insert): Likewise.
* config/tc-alpha.c (get_alpha_reloc_tag, md_begin): Likewise.
* config/tc-arc.c (arc_insert_opcode, declare_register): Likewise.
(declare_addrtype, md_begin, arc_extcorereg): Likewise.
* config/tc-arm.c (insert_reg_alias): Likewise.
(arm_tc_equal_in_insn, md_begin): Likewise.
* config/tc-cr16.c (initialise_reg_hash_table, md_begin): Likewise.
* config/tc-cris.c (md_begin): Likewise.
* config/tc-crx.c (md_begin): Likewise.
* config/tc-csky.c (md_begin): Likewise.
* config/tc-d10v.c (md_begin): Likewise.
* config/tc-dlx.c (md_begin): Likewise.
* config/tc-ft32.c (md_begin): Likewise.
* config/tc-h8300.c (md_begin): Likewise.
* config/tc-hppa.c (md_begin): Likewise.
* config/tc-i386.c (md_begin): Likewise.
* config/tc-ia64.c (dot_rot, dot_entry, declare_register): Likewise.
(md_begin, dot_alias): Likewise.
* config/tc-m68hc11.c (md_begin): Likewise.
* config/tc-m68k.c (md_begin): Likewise.
* config/tc-mcore.c (md_begin): Likewise.
* config/tc-microblaze.c (md_begin): Likewise.
* config/tc-mips.c (md_begin): Likewise.
* config/tc-mmix.c (md_begin): Likewise.
* config/tc-mn10200.c (md_begin): Likewise.
* config/tc-mn10300.c (md_begin): Likewise.
* config/tc-moxie.c (md_begin): Likewise.
* config/tc-nds32.c (nds32_relax_hint, md_begin): Likewise.
* config/tc-nios2.c (md_begin): Likewise.
* config/tc-ns32k.c (md_begin): Likewise.
* config/tc-pdp11.c (md_begin): Likewise.
* config/tc-pj.c (fake_opcode, md_begin): Likewise.
* config/tc-ppc.c (ppc_setup_opcodes): Likewise.
* config/tc-pru.c (md_begin): Likewise.
* config/tc-riscv.c (init_ext_version_hash): Likewise.
(init_opcode_names_hash, hash_reg_name, init_opcode_hash): Likewise.
(riscv_init_csr_hash): Likewise.
* config/tc-s390.c (s390_setup_opcodes, md_begin): Likewise.
* config/tc-score.c (s3_insert_reg): Likewise.
(s3_build_score_ops_hsh, s3_build_dependency_insn_hsh): Likewise.
* config/tc-score7.c (s7_build_score_ops_hsh): Likewise.
(s7_build_dependency_insn_hsh, s7_insert_reg): Likewise.
* config/tc-sh.c (md_begin): Likewise.
* config/tc-sparc.c (md_begin): Likewise.
* config/tc-spu.c (md_begin): Likewise.
* config/tc-tic30.c (md_begin): Likewise.
* config/tc-tic4x.c (tic4x_inst_insert): Likewise.
* config/tc-tic54x.c (stag_add_field_symbols, md_begin): Likewise.
(tic54x_endstruct, tic54x_var, tic54x_macro_info): Likewise.
(subsym_substitute): Likewise.
* config/tc-tilegx.c (md_begin): Likewise.
* config/tc-tilepro.c (md_begin): Likewise.
* config/tc-vax.c (vip_begin): Likewise.
* config/tc-wasm32.c (md_begin): Likewise.
* config/tc-xgate.c (md_begin): Likewise.
* config/tc-z8k.c (md_begin): Likewise.
* testsuite/gas/ppc/dcbt.d,
* testsuite/gas/ppc/dcbt.s: New test.
* testsuite/gas/ppc/ppc.exp: Run it.
* ecoff.c (add_string): Report fatal error on duplicates.
* config/tc-alpha.c (md_begin): Likewise.
* config/tc-arc.c (arc_insert_opcode, declare_register): Likewise.
(declare_addrtype, md_begin, arc_extcorereg): Likewise.
* config/tc-cr16.c (initialise_reg_hash_table, md_begin): Likewise.
* config/tc-cris.c (md_begin): Likewise.
* config/tc-crx.c (md_begin): Likewise.
* config/tc-dlx.c (md_begin): Likewise.
* config/tc-hppa.c (md_begin): Likewise.
* config/tc-i386.c (md_begin): Likewise.
* config/tc-ia64.c (dot_rot, dot_entry, declare_register): Likewise.
(md_begin): Likewise.
* config/tc-m68k.c (md_begin): Likewise.
* config/tc-mips.c (md_begin): Likewise.
* config/tc-nios2.c (md_begin): Likewise.
* config/tc-ns32k.c (md_begin): Likewise.
* config/tc-ppc.c (ppc_setup_opcodes): Likewise.
* config/tc-pru.c (md_begin): Likewise.
* config/tc-riscv.c (init_ext_version_hash): Likewise.
(init_opcode_names_hash, hash_reg_name, init_opcode_hash): Likewise.
* config/tc-s390.c (s390_setup_opcodes, md_begin): Likewise.
* config/tc-sparc.c (md_begin): Likewise.
* config/tc-tic30.c (md_begin): Likewise.
* config/tc-tic4x.c (tic4x_inst_insert): Likewise.
* config/tc-tilegx.c (md_begin): Likewise.
* config/tc-tilepro.c (md_begin): Likewise.
* config/tc-vax.c (vip_begin): Likewise.
* config/tc-alpha.c,
* config/tc-arm.c,
* config/tc-avr.c,
* config/tc-cr16.c,
* config/tc-csky.c,
* config/tc-i386.c,
* config/tc-m68hc11.c,
* config/tc-m68k.c,
* config/tc-microblaze.c,
* config/tc-ns32k.c,
* config/tc-pj.c,
* config/tc-ppc.c,
* config/tc-score.c,
* config/tc-score7.c,
* config/tc-tic4x.c,
* config/tc-tic54x.c,
* config/tc-tilegx.c,
* config/tc-tilepro.c,
* config/tc-xgate.c: Formatting.
2020-08-22 16:29:57 +08:00
|
|
|
free (copy);
|
1999-05-03 15:29:11 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Handle the MRI IRP and IRPC pseudo-ops. These are handled as a
|
|
|
|
combined macro definition and execution. This returns NULL on
|
|
|
|
success, or an error message otherwise. */
|
|
|
|
|
|
|
|
const char *
|
PR gas/14201
* sb.h (sb_max_power_two): Delete.
(struct sb): Delete "item" and "pot". Make "len" a size_t. Add "max".
(sb_element): Delete.
(sb_add_char, sb_add_buffer, sb_skip_comma, sb_skip_write): Update
prototypes.
* sb.c (string_count, free_list): Delete.
(sb_build, sb_kill, sb_check): Rewrite.
(scrub_from_sb, sb_add_char, sb_add_string, sb_add_buffer,
sb_skip_white, sb_skip_comma): Replace assorted int params,
vars and return types with size_t.
* input-scrub.c: Likewise.
* macro.c: Likewise.
* macro.h: Likewise.
* as.c: Likewise.
* as.h: Likewise.
* input-file.h: Likewise.
* input-file.c: Likewise.
* read.c: Likewise.
* app.c: ..or ptrdiff_t.
* input-file.c (input_file_get): Use ferror.
(input_file_give_next_buffer): Use input_file_get.
2012-06-07 20:47:23 +08:00
|
|
|
expand_irp (int irpc, size_t idx, sb *in, sb *out, size_t (*get_line) (sb *))
|
1999-05-03 15:29:11 +08:00
|
|
|
{
|
|
|
|
sb sub;
|
|
|
|
formal_entry f;
|
2020-08-16 01:47:01 +08:00
|
|
|
struct htab *h;
|
|
|
|
const char *err = NULL;
|
1999-05-03 15:29:11 +08:00
|
|
|
|
|
|
|
idx = sb_skip_white (idx, in);
|
|
|
|
|
|
|
|
sb_new (&sub);
|
2005-01-31 22:30:34 +08:00
|
|
|
if (! buffer_and_nest (NULL, "ENDR", &sub, get_line))
|
2023-03-22 06:22:11 +08:00
|
|
|
{
|
|
|
|
err = _("unexpected end of file in irp or irpc");
|
|
|
|
goto out2;
|
|
|
|
}
|
2000-09-01 02:36:18 +08:00
|
|
|
|
1999-05-03 15:29:11 +08:00
|
|
|
sb_new (&f.name);
|
|
|
|
sb_new (&f.def);
|
|
|
|
sb_new (&f.actual);
|
|
|
|
|
|
|
|
idx = get_token (idx, in, &f.name);
|
|
|
|
if (f.name.len == 0)
|
2023-03-22 06:22:11 +08:00
|
|
|
{
|
|
|
|
err = _("missing model parameter");
|
|
|
|
goto out1;
|
|
|
|
}
|
1999-05-03 15:29:11 +08:00
|
|
|
|
macro.c: use string hash from hash.h for macro_hash
Another case of duplicated hash.h code, the only minor difference
being that macro->format_hash was created with 7 entries vs. str_hash
with 16 entries.
* macro.c (macro_init, define_macro): Use str_htab_create.
(do_formals, define_macro, macro_expand_body): Use str_hash_insert
(macro_expand_body): Use str_hash_find and str_hash_delete.
(delete_macro): Likewise.
(sub_actual, macro_expand, check_macro): Use str_hash_find.
(expand_irp): Use str_htab_create and str_hash_insert.
* macro.h (struct macro_struct): Tidy.
(struct macro_hash_entry, macro_hash_entry_t, hash_macro_entry),
(eq_macro_entry, macro_entry_alloc, macro_entry_find),
(struct formal_hash_entry, formal_hash_entry_t),
(hash_formal_entry, eq_formal_entry, formal_entry_alloc),
(formal_entry_find): Delete.
* config/tc-iq2000.c (iq2000_add_macro): Use str_htab_create
and str_hash_insert.
2022-07-07 07:07:10 +08:00
|
|
|
h = str_htab_create ();
|
2020-08-16 01:47:01 +08:00
|
|
|
|
macro.c: use string hash from hash.h for macro_hash
Another case of duplicated hash.h code, the only minor difference
being that macro->format_hash was created with 7 entries vs. str_hash
with 16 entries.
* macro.c (macro_init, define_macro): Use str_htab_create.
(do_formals, define_macro, macro_expand_body): Use str_hash_insert
(macro_expand_body): Use str_hash_find and str_hash_delete.
(delete_macro): Likewise.
(sub_actual, macro_expand, check_macro): Use str_hash_find.
(expand_irp): Use str_htab_create and str_hash_insert.
* macro.h (struct macro_struct): Tidy.
(struct macro_hash_entry, macro_hash_entry_t, hash_macro_entry),
(eq_macro_entry, macro_entry_alloc, macro_entry_find),
(struct formal_hash_entry, formal_hash_entry_t),
(hash_formal_entry, eq_formal_entry, formal_entry_alloc),
(formal_entry_find): Delete.
* config/tc-iq2000.c (iq2000_add_macro): Use str_htab_create
and str_hash_insert.
2022-07-07 07:07:10 +08:00
|
|
|
str_hash_insert (h, sb_terminate (&f.name), &f, 0);
|
1999-05-03 15:29:11 +08:00
|
|
|
|
|
|
|
f.index = 1;
|
|
|
|
f.next = NULL;
|
2005-05-06 14:50:31 +08:00
|
|
|
f.type = FORMAL_OPTIONAL;
|
1999-05-03 15:29:11 +08:00
|
|
|
|
|
|
|
sb_reset (out);
|
|
|
|
|
|
|
|
idx = sb_skip_comma (idx, in);
|
2002-12-02 23:42:15 +08:00
|
|
|
if (idx >= in->len)
|
1999-05-03 15:29:11 +08:00
|
|
|
{
|
|
|
|
/* Expand once with a null string. */
|
2024-05-24 18:23:22 +08:00
|
|
|
err = macro_expand_body (&sub, out, &f, h, NULL, 0);
|
1999-05-03 15:29:11 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
Use bool in gas
* as.h (POISON_BFD_BOOLEAN): Define.
* as.c, * as.h, * atof-generic.c, * config/atof-ieee.c,
* config/bfin-aux.h, * config/obj-coff.c, * config/obj-ecoff.c,
* config/obj-elf.c, * config/obj-elf.h, * config/obj-som.c,
* config/tc-aarch64.c, * config/tc-alpha.c, * config/tc-arc.c,
* config/tc-arc.h, * config/tc-arm.c, * config/tc-arm.h,
* config/tc-avr.c, * config/tc-avr.h, * config/tc-bfin.c,
* config/tc-bfin.h, * config/tc-bpf.c, * config/tc-cris.c,
* config/tc-csky.c, * config/tc-csky.h, * config/tc-d10v.c,
* config/tc-d10v.h, * config/tc-d30v.c, * config/tc-d30v.h,
* config/tc-dlx.c, * config/tc-dlx.h, * config/tc-epiphany.c,
* config/tc-epiphany.h, * config/tc-fr30.c, * config/tc-fr30.h,
* config/tc-frv.c, * config/tc-frv.h, * config/tc-ft32.c,
* config/tc-ft32.h, * config/tc-h8300.c, * config/tc-hppa.c,
* config/tc-i386-intel.c, * config/tc-i386.c, * config/tc-ia64.c,
* config/tc-ip2k.c, * config/tc-iq2000.c, * config/tc-iq2000.h,
* config/tc-lm32.c, * config/tc-lm32.h, * config/tc-m32c.c,
* config/tc-m32c.h, * config/tc-m32r.c, * config/tc-m32r.h,
* config/tc-m68hc11.c, * config/tc-m68k.c, * config/tc-mcore.c,
* config/tc-mcore.h, * config/tc-mep.c, * config/tc-mep.h,
* config/tc-metag.c, * config/tc-metag.h,
* config/tc-microblaze.c, * config/tc-mips.c, * config/tc-mips.h,
* config/tc-mmix.c, * config/tc-mn10200.c, * config/tc-mn10300.c,
* config/tc-mn10300.h, * config/tc-moxie.c, * config/tc-msp430.c,
* config/tc-msp430.h, * config/tc-mt.c, * config/tc-mt.h,
* config/tc-nds32.c, * config/tc-nds32.h, * config/tc-nios2.c,
* config/tc-ns32k.c, * config/tc-or1k.c, * config/tc-or1k.h,
* config/tc-pdp11.c, * config/tc-ppc.c, * config/tc-pru.c,
* config/tc-pru.h, * config/tc-riscv.c, * config/tc-riscv.h,
* config/tc-rx.c, * config/tc-rx.h, * config/tc-s12z.c,
* config/tc-s12z.h, * config/tc-s390.c, * config/tc-score.c,
* config/tc-score.h, * config/tc-score7.c, * config/tc-sh.c,
* config/tc-sh.h, * config/tc-spu.c, * config/tc-tic54x.c,
* config/tc-tic6x.c, * config/tc-tic6x.h, * config/tc-tilegx.c,
* config/tc-tilepro.c, * config/tc-v850.c, * config/tc-v850.h,
* config/tc-visium.c, * config/tc-visium.h, * config/tc-wasm32.c,
* config/tc-wasm32.h, * config/tc-xc16x.c, * config/tc-xgate.c,
* config/tc-xstormy16.c, * config/tc-xstormy16.h,
* config/tc-xtensa.c, * config/tc-xtensa.h, * config/tc-z80.c,
* config/tc-z8k.c, * config/xtensa-istack.h,
* config/xtensa-relax.c, * config/xtensa-relax.h, * dw2gencfi.c,
* dwarf2dbg.c, * dwarf2dbg.h, * expr.c, * expr.h, * frags.c,
* frags.h, * listing.c, * macro.c, * output-file.c, * read.c,
* read.h, * stabs.c, * symbols.c, * write.c: Replace bfd_boolean
with bool, FALSE with false, and TRUE with true.
2021-03-31 08:12:05 +08:00
|
|
|
bool in_quotes = false;
|
2024-05-24 18:23:22 +08:00
|
|
|
unsigned int instance = 0;
|
2007-01-12 18:57:02 +08:00
|
|
|
|
2002-12-02 23:42:15 +08:00
|
|
|
while (idx < in->len)
|
1999-05-03 15:29:11 +08:00
|
|
|
{
|
|
|
|
if (!irpc)
|
2005-05-10 15:48:24 +08:00
|
|
|
idx = get_any_string (idx, in, &f.actual);
|
1999-05-03 15:29:11 +08:00
|
|
|
else
|
|
|
|
{
|
|
|
|
if (in->ptr[idx] == '"')
|
|
|
|
{
|
2024-05-24 18:22:54 +08:00
|
|
|
in_quotes = ! in_quotes;
|
|
|
|
++idx;
|
1999-05-03 15:29:11 +08:00
|
|
|
|
2024-05-24 18:22:54 +08:00
|
|
|
if (! in_quotes)
|
1999-05-03 15:29:11 +08:00
|
|
|
{
|
2024-05-24 18:22:54 +08:00
|
|
|
idx = sb_skip_white (idx, in);
|
|
|
|
if (idx >= in->len)
|
|
|
|
break;
|
1999-05-03 15:29:11 +08:00
|
|
|
}
|
2024-08-14 17:25:34 +08:00
|
|
|
continue;
|
1999-05-03 15:29:11 +08:00
|
|
|
}
|
|
|
|
sb_reset (&f.actual);
|
|
|
|
sb_add_char (&f.actual, in->ptr[idx]);
|
|
|
|
++idx;
|
|
|
|
}
|
2007-01-12 18:57:02 +08:00
|
|
|
|
2024-05-24 18:23:22 +08:00
|
|
|
err = macro_expand_body (&sub, out, &f, h, NULL, instance);
|
|
|
|
++instance;
|
1999-05-03 15:29:11 +08:00
|
|
|
if (err != NULL)
|
2005-04-25 14:43:46 +08:00
|
|
|
break;
|
1999-05-03 15:29:11 +08:00
|
|
|
if (!irpc)
|
|
|
|
idx = sb_skip_comma (idx, in);
|
2007-01-12 18:57:02 +08:00
|
|
|
else if (! in_quotes)
|
1999-05-03 15:29:11 +08:00
|
|
|
idx = sb_skip_white (idx, in);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-16 01:47:01 +08:00
|
|
|
htab_delete (h);
|
2023-03-22 06:22:11 +08:00
|
|
|
out1:
|
2005-05-06 14:50:31 +08:00
|
|
|
sb_kill (&f.actual);
|
|
|
|
sb_kill (&f.def);
|
|
|
|
sb_kill (&f.name);
|
2023-03-22 06:22:11 +08:00
|
|
|
out2:
|
1999-05-03 15:29:11 +08:00
|
|
|
sb_kill (&sub);
|
|
|
|
|
2005-04-25 14:43:46 +08:00
|
|
|
return err;
|
1999-05-03 15:29:11 +08:00
|
|
|
}
|