/* gasp.c - Gnu assembler preprocessor main program.
- Copyright (C) 1994 Free Software Foundation, Inc.
+ Copyright (C) 1994, 95, 96, 97, 1998 Free Software Foundation, Inc.
Written by Steve and Judy Chamberlain of Cygnus Support,
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with GASP; see the file COPYING. If not, write to
- the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+ along with GASP; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
/*
-a use alternate syntax
Pseudo ops can start with or without a .
Labels have to be in first column.
+ -I specify include dir
Macro arg parameters subsituted by name, don't need the &.
String can start with ' too.
Strings can be surrounded by <..>
extern char *malloc ();
#endif
+#include "ansidecl.h"
#include "libiberty.h"
+#include "sb.h"
+#include "macro.h"
+#include "asintl.h"
char *program_version = "1.2";
+/* This is normally declared in as.h, but we don't include that. We
+ need the function because other files linked with gasp.c might call
+ it. */
+extern void as_abort PARAMS ((const char *, int, const char *));
+
#define MAX_INCLUDES 30 /* Maximum include depth */
#define MAX_REASONABLE 1000 /* Maximum number of expansions */
int errors; /* Number of ERRORs generated so far. */
int fatals; /* Number of fatal ERRORs generated so far (either 0 or 1). */
int alternate = 0; /* -a on command line */
+int mri = 0; /* -M on command line */
char comment_char = '!';
int radix = 10; /* Default radix */
/* The output stream */
FILE *outfile;
-
-/* Forward declarations. */
-static int condass_lookup_name();
-static int condass_on();
-static int get();
-static int get_and_process();
-static int get_token();
-static int getstring();
-static int include_next_index();
-static int macro_op();
-static int linecount();
-static int process_pseudo_op();
-static void include_pop();
-static void include_print_where_line();
-/* string blocks
-
- I had a couple of choices when deciding upon this data structure.
- gas uses null terminated strings for all its internal work. This
- often means that parts of the program that want to examine
- substrings have to manipulate the data in the string to do the
- right thing (a common operation is to single out a bit of text by
- saving away the character after it, nulling it out, operating on
- the substring and then replacing the character which was under the
- null). This is a pain and I remember a load of problems that I had with
- code in gas which almost got this right. Also, it's harder to grow and
- allocate null terminated strings efficiently.
-
- Obstacks provide all the functionality needed, but are too
- complicated, hence the sb.
-
- An sb is allocated by the caller, and is initialzed to point to an
- sb_element. sb_elements are kept on a free lists, and used when
- needed, replaced onto the free list when unused.
- */
-
-#define max_power_two 30 /* don't allow strings more than
- 2^max_power_two long */
-/* structure of an sb */
-typedef struct sb
- {
- char *ptr; /* points to the current block. */
- int len; /* how much is used. */
- int pot; /* the maximum length is 1<<pot */
- struct le *item;
- }
-sb;
-
-/* Structure of the free list object of an sb */
-typedef struct le
- {
- struct le *next;
- int size;
- char data[1];
- }
-sb_element;
-
-/* The free list */
-typedef struct
- {
- sb_element *size[max_power_two];
- } sb_list_vector;
-
-sb_list_vector free_list;
-
-int string_count[max_power_two];
-
/* the attributes of each character are stored as a bit pattern
chartype, which gives us quick tests. */
#define WHITEBIT 8
#define COMMENTBIT 16
#define BASEBIT 32
-#define ISCOMMENTCHAR(x) (chartype[(unsigned)(x)] & COMMENTBIT)
-#define ISFIRSTCHAR(x) (chartype[(unsigned)(x)] & FIRSTBIT)
-#define ISNEXTCHAR(x) (chartype[(unsigned)(x)] & NEXTBIT)
-#define ISSEP(x) (chartype[(unsigned)(x)] & SEPBIT)
-#define ISWHITE(x) (chartype[(unsigned)(x)] & WHITEBIT)
-#define ISBASE(x) (chartype[(unsigned)(x)] & BASEBIT)
+#define ISCOMMENTCHAR(x) (chartype[(unsigned char)(x)] & COMMENTBIT)
+#define ISFIRSTCHAR(x) (chartype[(unsigned char)(x)] & FIRSTBIT)
+#define ISNEXTCHAR(x) (chartype[(unsigned char)(x)] & NEXTBIT)
+#define ISSEP(x) (chartype[(unsigned char)(x)] & SEPBIT)
+#define ISWHITE(x) (chartype[(unsigned char)(x)] & WHITEBIT)
+#define ISBASE(x) (chartype[(unsigned char)(x)] & BASEBIT)
static char chartype[256];
struct include_stack *sp;
#define isp (sp - include_stack)
-#define dsize 5
-
-
-void include_print_where_line ();
-
+/* Include file list */
+
+typedef struct include_path
+{
+ struct include_path *next;
+ sb path;
+} include_path;
+
+include_path *paths_head;
+include_path *paths_tail;
+
+
+static void quit PARAMS ((void));
+static void hash_new_table PARAMS ((int, hash_table *));
+static int hash PARAMS ((sb *));
+static hash_entry *hash_create PARAMS ((hash_table *, sb *));
+static void hash_add_to_string_table PARAMS ((hash_table *, sb *, sb *, int));
+static void hash_add_to_int_table PARAMS ((hash_table *, sb *, int));
+static hash_entry *hash_lookup PARAMS ((hash_table *, sb *));
+static void checkconst PARAMS ((int, exp_t *));
+static int sb_strtol PARAMS ((int, sb *, int, int *));
+static int level_0 PARAMS ((int, sb *, exp_t *));
+static int level_1 PARAMS ((int, sb *, exp_t *));
+static int level_2 PARAMS ((int, sb *, exp_t *));
+static int level_3 PARAMS ((int, sb *, exp_t *));
+static int level_4 PARAMS ((int, sb *, exp_t *));
+static int level_5 PARAMS ((int, sb *, exp_t *));
+static int exp_parse PARAMS ((int, sb *, exp_t *));
+static void exp_string PARAMS ((exp_t *, sb *));
+static int exp_get_abs PARAMS ((const char *, int, sb *, int *));
+#if 0
+static void strip_comments PARAMS ((sb *));
+#endif
+static void unget PARAMS ((int));
+static void include_buf PARAMS ((sb *, sb *, include_type, int));
+static void include_print_where_line PARAMS ((FILE *));
+static void include_print_line PARAMS ((FILE *));
+static int get_line PARAMS ((sb *));
+static int grab_label PARAMS ((sb *, sb *));
+static void change_base PARAMS ((int, sb *, sb *));
+static void do_end PARAMS ((sb *));
+static void do_assign PARAMS ((int, int, sb *));
+static void do_radix PARAMS ((sb *));
+static int get_opsize PARAMS ((int, sb *, int *));
+static int eol PARAMS ((int, sb *));
+static void do_data PARAMS ((int, sb *, int));
+static void do_datab PARAMS ((int, sb *));
+static void do_align PARAMS ((int, sb *));
+static void do_res PARAMS ((int, sb *, int));
+static void do_export PARAMS ((sb *));
+static void do_print PARAMS ((int, sb *));
+static void do_heading PARAMS ((int, sb *));
+static void do_page PARAMS ((void));
+static void do_form PARAMS ((int, sb *));
+static int get_any_string PARAMS ((int, sb *, sb *, int, int));
+static int skip_openp PARAMS ((int, sb *));
+static int skip_closep PARAMS ((int, sb *));
+static int dolen PARAMS ((int, sb *, sb *));
+static int doinstr PARAMS ((int, sb *, sb *));
+static int dosubstr PARAMS ((int, sb *, sb *));
+static void process_assigns PARAMS ((int, sb *, sb *));
+static int get_and_process PARAMS ((int, sb *, sb *));
+static void process_file PARAMS ((void));
+static void free_old_entry PARAMS ((hash_entry *));
+static void do_assigna PARAMS ((int, sb *));
+static void do_assignc PARAMS ((int, sb *));
+static void do_reg PARAMS ((int, sb *));
+static int condass_lookup_name PARAMS ((sb *, int, sb *, int));
+static int whatcond PARAMS ((int, sb *, int *));
+static int istrue PARAMS ((int, sb *));
+static void do_aif PARAMS ((int, sb *));
+static void do_aelse PARAMS ((void));
+static void do_aendi PARAMS ((void));
+static int condass_on PARAMS ((void));
+static void do_if PARAMS ((int, sb *, int));
+static int get_mri_string PARAMS ((int, sb *, sb *, int));
+static void do_ifc PARAMS ((int, sb *, int));
+static void do_aendr PARAMS ((void));
+static void do_awhile PARAMS ((int, sb *));
+static void do_aendw PARAMS ((void));
+static void do_exitm PARAMS ((void));
+static void do_arepeat PARAMS ((int, sb *));
+static void do_endm PARAMS ((void));
+static void do_irp PARAMS ((int, sb *, int));
+static void do_local PARAMS ((int, sb *));
+static void do_macro PARAMS ((int, sb *));
+static int macro_op PARAMS ((int, sb *));
+static int getstring PARAMS ((int, sb *, sb *));
+static void do_sdata PARAMS ((int, sb *, int));
+static void do_sdatab PARAMS ((int, sb *));
+static int new_file PARAMS ((const char *));
+static void do_include PARAMS ((int, sb *));
+static void include_pop PARAMS ((void));
+static int get PARAMS ((void));
+static int linecount PARAMS ((void));
+static int include_next_index PARAMS ((void));
+static void chartype_init PARAMS ((void));
+static int process_pseudo_op PARAMS ((int, sb *, sb *));
+static void add_keyword PARAMS ((const char *, int));
+static void process_init PARAMS ((void));
+static void do_define PARAMS ((const char *));
+static void show_usage PARAMS ((FILE *, int));
+static void show_help PARAMS ((void));
#define FATAL(x) \
do { include_print_where_line (stderr); fprintf x ; fatals++; quit(); } while(0)
/* exit the program and return the right ERROR code. */
-void
+static void
quit ()
{
int exitcode;
if (stats)
{
int i;
- for (i = 0; i < max_power_two; i++)
+ for (i = 0; i < sb_max_power_two; i++)
{
fprintf (stderr, "strings size %8d : %d\n", 1<<i, string_count[i]);
}
exit (exitcode);
}
-
-/* this program is about manipulating strings.
- they are managed in things called `sb's which is an abbreviation
- for string buffers. an sb has to be created, things can be glued
- on to it, and at the end of it's life it should be freed. the
- contents should never be pointed at whilst it is still growing,
- since it could be moved at any time
-
- eg:
- sb_new (&foo);
- sb_grow... (&foo,...);
- use foo->ptr[*];
- sb_kill (&foo);
-
-*/
-
-/* initializes an sb. */
-
-void
-sb_build (ptr, size)
- sb *ptr;
- int size;
-{
- /* see if we can find one to allocate */
- sb_element *e;
-
- if (size > max_power_two)
- {
- FATAL ((stderr, "string longer than %d bytes requested.\n",
- 1 << max_power_two));
- }
- e = free_list.size[size];
- if (!e)
- {
- /* nothing there, allocate one and stick into the free list */
- e = (sb_element *) xmalloc (sizeof (sb_element) + (1 << size));
- e->next = free_list.size[size];
- e->size = 1 << size;
- free_list.size[size] = e;
- string_count[size]++;
- }
-
- /* remove from free list */
-
- free_list.size[size] = e->next;
-
- /* copy into callers world */
- ptr->ptr = e->data;
- ptr->pot = size;
- ptr->len = 0;
- ptr->item = e;
-}
-
-
-static void
-sb_new (ptr)
- sb *ptr;
-{
- sb_build (ptr, dsize);
-}
-
-/* deallocate the sb at ptr */
-
-static
-void
-sb_kill (ptr)
- sb *ptr;
-{
- /* return item to free list */
- ptr->item->next = free_list.size[ptr->pot];
- free_list.size[ptr->pot] = ptr->item;
-}
-
-/* add the sb at s to the end of the sb at ptr */
-
-static void sb_check ();
-
-static
-void
-sb_add_sb (ptr, s)
- sb *ptr;
- sb *s;
-{
- sb_check (ptr, s->len);
- memcpy (ptr->ptr + ptr->len, s->ptr, s->len);
- ptr->len += s->len;
-}
-
-/* make sure that the sb at ptr has room for another len characters,
- and grow it if it doesn't. */
-
-static void
-sb_check (ptr, len)
- sb *ptr;
- int len;
-{
- if (ptr->len + len >= 1 << ptr->pot)
- {
- sb tmp;
- int pot = ptr->pot;
- while (ptr->len + len >= 1 << pot)
- pot++;
- sb_build (&tmp, pot);
- sb_add_sb (&tmp, ptr);
- sb_kill (ptr);
- *ptr = tmp;
- }
-}
-
-/* make the sb at ptr point back to the beginning. */
-
-static void
-sb_reset (ptr)
- sb *ptr;
-{
- ptr->len = 0;
-}
-
-/* add character c to the end of the sb at ptr. */
-
-void
-sb_add_char (ptr, c)
- sb *ptr;
- char c;
-{
- sb_check (ptr, 1);
- ptr->ptr[ptr->len++] = c;
-}
-
-/* add null terminated string s to the end of sb at ptr. */
-
-static void
-sb_add_string (ptr, s)
- sb *ptr;
- char *s;
-{
- int len = strlen (s);
- sb_check (ptr, len);
- memcpy (ptr->ptr + ptr->len, s, len);
- ptr->len += len;
-}
-
-/* add string at s of length len to sb at ptr */
-
-static void
-sb_add_buffer (ptr, s, len)
- sb *ptr;
- char *s;
- int len;
-{
- sb_check (ptr, len);
- memcpy (ptr->ptr + ptr->len, s, len);
- ptr->len += len;
-}
-
-
-/* print the sb at ptr to the output file */
-
-static
-void
-sb_print (ptr)
- sb *ptr;
-{
- int i;
- int nc = 0;
-
- for (i = 0; i < ptr->len; i++)
- {
- if (nc)
- {
- fprintf (outfile, ",");
- }
- fprintf (outfile, "%d", ptr->ptr[i]);
- nc = 1;
- }
-}
-
-static
-void
-sb_print_at (idx, ptr)
-int idx;
-sb *ptr;
-{
- int i;
- for (i = idx; i < ptr->len; i++)
- putc (ptr->ptr[i], outfile);
-}
-/* put a null at the end of the sb at in and return the start of the
- string, so that it can be used as an arg to printf %s. */
-
-static
-char *
-sb_name (in)
- sb *in;
-{
- /* stick a null on the end of the string */
- sb_add_char (in, 0);
- return in->ptr;
-}
-
-/* start at the index idx into the string in sb at ptr and skip
- whitespace. return the index of the first non whitespace character */
-
-static int
-sb_skip_white (idx, ptr)
- int idx;
- sb *ptr;
-{
- while (idx < ptr->len && ISWHITE (ptr->ptr[idx]))
- idx++;
- return idx;
-}
-
-/* start at the index idx into the sb at ptr. skips whitespace,
- a comma and any following whitespace. returnes the index of the
- next character. */
-
-static int
-sb_skip_comma (idx, ptr)
- int idx;
- sb *ptr;
-{
- while (idx < ptr->len && ISWHITE (ptr->ptr[idx]))
- idx++;
-
- if (idx < ptr->len
- && ptr->ptr[idx] == ',')
- idx++;
-
- while (idx < ptr->len && ISWHITE (ptr->ptr[idx]))
- idx++;
-
- return idx;
-}
-
-
/* hash table maintenance. */
/* build a new hash table with size buckets, and fill in the info at ptr. */
if (ptr->value.s.len)
{
if (!again)
- ERROR ((stderr, "redefintion not allowed"));
+ ERROR ((stderr, _("redefinition not allowed\n")));
}
ptr->type = hash_string;
static
void
checkconst (op, term)
- char op;
+ int op;
exp_t *term;
{
if (term->add_symbol.len
|| term->sub_symbol.len)
{
- ERROR ((stderr, "the %c operator cannot take non-absolute arguments.\n", op));
+ ERROR ((stderr, _("the %c operator cannot take non-absolute arguments.\n"), op));
}
}
return idx;
}
-static int level_5 ();
-
-int
+static int
level_0 (idx, string, lhs)
int idx;
sb *string;
lhs->value = 0;
- if (isdigit (string->ptr[idx]))
+ if (isdigit ((unsigned char) string->ptr[idx]))
{
idx = sb_strtol (idx, string, 10, &lhs->value);
}
{
sb acc;
sb_new (&acc);
- ERROR ((stderr, "string where expression expected.\n"));
+ ERROR ((stderr, _("string where expression expected.\n")));
idx = getstring (idx, string, &acc);
sb_kill (&acc);
}
else
{
- ERROR ((stderr, "can't find primary in expression.\n"));
+ ERROR ((stderr, _("can't find primary in expression.\n")));
idx++;
}
return sb_skip_white (idx, string);
idx++;
idx = level_5 (sb_skip_white (idx, string), string, lhs);
if (string->ptr[idx] != ')')
- ERROR ((stderr, "misplaced closing parens.\n"));
+ ERROR ((stderr, _("misplaced closing parens.\n")));
else
idx++;
break;
checkconst ('/', lhs);
checkconst ('/', &rhs);
if (rhs.value == 0)
- ERROR ((stderr, "attempt to divide by zero.\n"));
+ ERROR ((stderr, _("attempt to divide by zero.\n")));
else
lhs->value /= rhs.value;
break;
lhs->value += rhs.value;
if (lhs->add_symbol.name && rhs.add_symbol.name)
{
- ERROR ((stderr, "can't add two relocatable expressions\n"));
+ ERROR ((stderr, _("can't add two relocatable expressions\n")));
}
/* change nn+symbol to symbol + nn */
if (rhs.add_symbol.name)
static int
exp_get_abs (emsg, idx, in, val)
- char *emsg;
+ const char *emsg;
int idx;
sb *in;
int *val;
#define in_comment ';'
-#if 1
-void
+#if 0
+static void
strip_comments (out)
sb *out;
{
/* push back character ch so that it can be read again. */
-void
+static void
unget (ch)
int ch;
{
{
sp++;
if (sp - include_stack >= MAX_INCLUDES)
- FATAL ((stderr, "unreasonable nesting.\n"));
+ FATAL ((stderr, _("unreasonable nesting.\n")));
sb_new (&sp->name);
sb_add_sb (&sp->name, name);
sp->handle = 0;
while (p <= sp)
{
- fprintf (file, "%s:%d ", sb_name (&p->name), p->linecount - ((p == sp) ? 1 : 0));
+ fprintf (file, "%s:%d ", sb_name (&p->name), p->linecount - 1);
p++;
}
}
{
if (online)
{
- WARNING ((stderr, "End of file not at start of line.\n"));
+ WARNING ((stderr, _("End of file not at start of line.\n")));
if (copysource)
putc ('\n', outfile);
ch = '\n';
{
int i = 0;
sb_reset (out);
- if (ISFIRSTCHAR (in->ptr[i]))
+ if (ISFIRSTCHAR (in->ptr[i]) || in->ptr[i] == '\\')
{
sb_add_char (out, in->ptr[i]);
i++;
while (idx < in->len)
{
- if (idx < in->len - 1 && in->ptr[idx + 1] == '\'')
+ if (in->ptr[idx] == '\\'
+ && idx + 1 < in->len
+ && in->ptr[idx + 1] == '(')
+ {
+ idx += 2;
+ while (idx < in->len
+ && in->ptr[idx] != ')')
+ {
+ sb_add_char (out, in->ptr[idx]);
+ idx++;
+ }
+ if (idx < in->len)
+ idx++;
+ }
+ else if (idx < in->len - 1 && in->ptr[idx + 1] == '\'' && ! mri)
{
int base;
int value;
base = 10;
break;
default:
- ERROR ((stderr, "Illegal base character %c.\n", in->ptr[idx]));
+ ERROR ((stderr, _("Illegal base character %c.\n"), in->ptr[idx]));
base = 10;
break;
}
idx++;
}
}
- else if (isdigit (in->ptr[idx]))
+ else if (isdigit ((unsigned char) in->ptr[idx]))
{
int value;
/* all numbers must start with a digit, let's chew it and
/* .end */
static void
-do_end ()
+do_end (in)
+ sb *in;
{
had_end = 1;
+ if (mri)
+ fprintf (outfile, "%s\n", sb_name (in));
}
/* .assign */
radix = 16;
break;
default:
- ERROR ((stderr, "radix is %c must be one of b, q, d or h", radix));
+ ERROR ((stderr, _("radix is %c must be one of b, q, d or h"), radix));
}
}
static int
get_opsize (idx, in, size)
-int idx;
-sb *in;
-int *size;
+ int idx;
+ sb *in;
+ int *size;
{
*size = 4;
if (in->ptr[idx] == '.')
case '\t':
break;
default:
- ERROR ((stderr, "size must be one of b, w or l, is %c.\n", in->ptr[idx]));
+ ERROR ((stderr, _("size must be one of b, w or l, is %c.\n"), in->ptr[idx]));
break;
}
idx++;
static
int eol(idx, line)
-int idx;
-sb *line;
+ int idx;
+ sb *line;
{
idx = sb_skip_white (idx, line);
if (idx < line->len
}
}
sb_kill (&acc);
- sb_print_at (idx, in);
+ sb_print_at (outfile, idx, in);
fprintf (outfile, "\n");
}
idx = get_opsize (idx, in, &opsize);
- idx = exp_get_abs ("datab repeat must be constant.\n", idx, in, &repeat);
+ idx = exp_get_abs (_("datab repeat must be constant.\n"), idx, in, &repeat);
idx = sb_skip_comma (idx, in);
- idx = exp_get_abs ("datab data must be absolute.\n", idx, in, &fill);
+ idx = exp_get_abs (_("datab data must be absolute.\n"), idx, in, &fill);
fprintf (outfile, ".fill\t%d,%d,%d\n", repeat, opsize, fill);
}
/* .align <size> */
-void
+static void
do_align (idx, in)
int idx;
sb *in;
{
- int al;
- idx = exp_get_abs ("align needs absolute expression.\n", idx, in, &al);
+ int al, have_fill, fill;
+
+ idx = exp_get_abs (_("align needs absolute expression.\n"), idx, in, &al);
+ idx = sb_skip_white (idx, in);
+ have_fill = 0;
+ fill = 0;
+ if (! eol (idx, in))
+ {
+ idx = sb_skip_comma (idx, in);
+ idx = exp_get_abs (_(".align needs absolute fill value.\n"), idx, in,
+ &fill);
+ have_fill = 1;
+ }
if (al != 1
&& al != 2
&& al != 4)
- WARNING ((stderr, "alignment must be one of 1, 2 or 4.\n"));
+ WARNING ((stderr, _("alignment must be one of 1, 2 or 4.\n")));
- fprintf (outfile, ".align %d\n", al);
+ fprintf (outfile, ".align %d", al);
+ if (have_fill)
+ fprintf (outfile, ",%d", fill);
+ fprintf (outfile, "\n");
}
/* .res[.b|.w|.l] <size> */
-void
+static void
do_res (idx, in, type)
int idx;
sb *in;
- char type;
+ int type;
{
int size = 4;
int count = 0;
idx = sb_skip_white (idx, in);
if (in->ptr[idx] == ',')
idx++;
- idx = exp_get_abs ("res needs absolute expression for fill count.\n", idx, in, &count);
+ idx = exp_get_abs (_("res needs absolute expression for fill count.\n"), idx, in, &count);
if (type == 'c' || type == 'z')
count++;
/* .export */
-void
+static void
do_export (in)
sb *in;
{
/* .print [list] [nolist] */
-void
+static void
do_print (idx, in)
int idx;
sb *in;
}
/* .head */
-void
+static void
do_heading (idx, in)
int idx;
sb *in;
/* .page */
-void
+static void
do_page ()
{
fprintf (outfile, ".eject\n");
}
/* .form [lin=<value>] [col=<value>] */
-void
+static void
do_form (idx, in)
int idx;
sb *in;
if (strncasecmp (in->ptr + idx, "LIN=", 4) == 0)
{
idx += 4;
- idx = exp_get_abs ("form LIN= needs absolute expresssion.\n", idx, in, &lines);
+ idx = exp_get_abs (_("form LIN= needs absolute expresssion.\n"), idx, in, &lines);
}
- if (strncasecmp (in->ptr + idx, "COL=", 4) == 0)
+ if (strncasecmp (in->ptr + idx, _("COL="), 4) == 0)
{
idx += 4;
- idx = exp_get_abs ("form COL= needs absolute expresssion.\n", idx, in, &columns);
+ idx = exp_get_abs (_("form COL= needs absolute expresssion.\n"), idx, in, &columns);
}
idx++;
"<string>" -> return string
xyx<whitespace> -> return xyz
*/
-int
+static int
get_any_string (idx, in, out, expand, pretend_quoted)
int idx;
sb *in;
int val;
char buf[20];
/* Turns the next expression into a string */
- idx = exp_get_abs ("% operator needs absolute expression",
+ idx = exp_get_abs (_("% operator needs absolute expression"),
idx + 1,
in,
&val);
if (alternate && expand)
{
/* Keep the quotes */
- sb_add_char (out, '\"');
+ sb_add_char (out, '\"');
idx = getstring (idx, in, out);
- sb_add_char (out, '\"');
+ sb_add_char (out, '\"');
}
else {
/* skip along sb in starting at idx, suck off whitespace a ( and more
whitespace. return the idx of the next char */
-int
+static int
skip_openp (idx, in)
int idx;
sb *in;
{
idx = sb_skip_white (idx, in);
if (in->ptr[idx] != '(')
- ERROR ((stderr, "misplaced ( .\n"));
+ ERROR ((stderr, _("misplaced ( .\n")));
idx = sb_skip_white (idx + 1, in);
return idx;
}
/* skip along sb in starting at idx, suck off whitespace a ) and more
whitespace. return the idx of the next char */
-int
+static int
skip_closep (idx, in)
int idx;
sb *in;
{
idx = sb_skip_white (idx, in);
if (in->ptr[idx] != ')')
- ERROR ((stderr, "misplaced ).\n"));
+ ERROR ((stderr, _("misplaced ).\n")));
idx = sb_skip_white (idx + 1, in);
return idx;
}
/* .len */
-int
+static int
dolen (idx, in, out)
int idx;
sb *in;
idx = sb_skip_comma (idx, in);
idx = get_and_process (idx, in, &search);
idx = sb_skip_comma (idx, in);
- if (isdigit (in->ptr[idx]))
+ if (isdigit ((unsigned char) in->ptr[idx]))
{
- idx = exp_get_abs (".instr needs absolute expresson.\n", idx, in, &start);
+ idx = exp_get_abs (_(".instr needs absolute expresson.\n"), idx, in, &start);
}
else
{
idx = skip_openp (idx, in);
idx = get_and_process (idx, in, &string);
idx = sb_skip_comma (idx, in);
- idx = exp_get_abs ("need absolute position.\n", idx, in, &pos);
+ idx = exp_get_abs (_("need absolute position.\n"), idx, in, &pos);
idx = sb_skip_comma (idx, in);
- idx = exp_get_abs ("need absolute length.\n", idx, in, &len);
+ idx = exp_get_abs (_("need absolute length.\n"), idx, in, &len);
idx = skip_closep (idx, in);
}
/* scan line, change tokens in the hash table to their replacements */
-void
+static void
process_assigns (idx, in, buf)
int idx;
sb *in;
{
hash_entry *ptr;
if (in->ptr[idx] == '\\'
+ && idx + 1 < in->len
+ && in->ptr[idx + 1] == '(')
+ {
+ do
+ {
+ sb_add_char (buf, in->ptr[idx]);
+ idx++;
+ }
+ while (idx < in->len && in->ptr[idx - 1] != ')');
+ }
+ else if (in->ptr[idx] == '\\'
+ && idx + 1 < in->len
&& in->ptr[idx + 1] == '&')
{
idx = condass_lookup_name (in, idx + 2, buf, 1);
}
else if (in->ptr[idx] == '\\'
+ && idx + 1 < in->len
&& in->ptr[idx + 1] == '$')
{
idx = condass_lookup_name (in, idx + 2, buf, 0);
if (condass_on ())
fprintf (outfile, "\n");
}
+ else if (mri
+ && (line.ptr[0] == '*'
+ || line.ptr[0] == '!'))
+ {
+ /* MRI line comment. */
+ fprintf (outfile, sb_name (&line));
+ }
else
{
l = grab_label (&line, &label_in);
sb_reset (&label);
- if (label_in.len)
- {
- /* Munge any label */
-
-
- process_assigns (0, &label_in, &label);
- }
if (line.ptr[l] == ':')
l++;
while (ISWHITE (line.ptr[l]) && l < line.len)
l++;
+ if (label_in.len)
+ {
+ int do_assigns;
+
+ /* Munge the label, unless this is EQU or ASSIGN. */
+ do_assigns = 1;
+ if (l < line.len
+ && (line.ptr[l] == '.' || alternate || mri))
+ {
+ int lx = l;
+
+ if (line.ptr[lx] == '.')
+ ++lx;
+ if (lx + 3 <= line.len
+ && strncasecmp ("EQU", line.ptr + lx, 3) == 0
+ && (lx + 3 == line.len
+ || ! ISFIRSTCHAR (line.ptr[lx + 3])))
+ do_assigns = 0;
+ else if (lx + 6 <= line.len
+ && strncasecmp ("ASSIGN", line.ptr + lx, 6) == 0
+ && (lx + 6 == line.len
+ || ! ISFIRSTCHAR (line.ptr[lx + 6])))
+ do_assigns = 0;
+ }
+
+ if (do_assigns)
+ process_assigns (0, &label_in, &label);
+ else
+ sb_add_sb (&label, &label_in);
+ }
+
if (l < line.len)
{
if (process_pseudo_op (l, &line, &acc))
more = get_line (&line);
}
- if (!had_end)
- WARNING ((stderr, "END missing from end of file.\n"));
+ if (!had_end && !mri)
+ WARNING ((stderr, _("END missing from end of file.\n")));
}
/* name: .ASSIGNA <value> */
-void
+static void
do_assigna (idx, in)
int idx;
sb *in;
sb_new (&tmp);
process_assigns (idx, in, &tmp);
- idx = exp_get_abs (".ASSIGNA needs constant expression argument.\n", 0, &tmp, &val);
+ idx = exp_get_abs (_(".ASSIGNA needs constant expression argument.\n"), 0, &tmp, &val);
if (!label.len)
{
- ERROR ((stderr, ".ASSIGNA without label.\n"));
+ ERROR ((stderr, _(".ASSIGNA without label.\n")));
}
else
{
/* name: .ASSIGNC <string> */
-void
+static void
do_assignc (idx, in)
int idx;
sb *in;
if (!label.len)
{
- ERROR ((stderr, ".ASSIGNS without label.\n"));
+ ERROR ((stderr, _(".ASSIGNS without label.\n")));
}
else
{
{
/* remove reg stuff from inside parens */
sb what;
- idx = skip_openp (idx, in);
+ if (!mri)
+ idx = skip_openp (idx, in);
+ else
+ idx = sb_skip_white (idx, in);
sb_new (&what);
- while (idx < in->len && in->ptr[idx] != ')')
+ while (idx < in->len
+ && (mri
+ ? ! eol (idx, in)
+ : in->ptr[idx] != ')'))
{
sb_add_char (&what, in->ptr[idx]);
idx++;
{
if (warn)
{
- WARNING ((stderr, "Can't find preprocessor variable %s.\n", sb_name (&condass_acc)));
+ WARNING ((stderr, _("Can't find preprocessor variable %s.\n"), sb_name (&condass_acc)));
}
else
{
#define GT 6
#define NEVER 7
-int
+static int
whatcond (idx, in, val)
int idx;
sb *in;
}
if (cond == NEVER)
{
- ERROR ((stderr, "Comparison operator must be one of EQ, NE, LT, LE, GT or GE.\n"));
+ ERROR ((stderr, _("Comparison operator must be one of EQ, NE, LT, LE, GT or GE.\n")));
cond = NEVER;
}
idx = sb_skip_white (idx + 2, in);
return idx;
}
-int
+static int
istrue (idx, in)
int idx;
sb *in;
if (cond != EQ && cond != NE)
{
- ERROR ((stderr, "Comparison operator for strings must be EQ or NE\n"));
+ ERROR ((stderr, _("Comparison operator for strings must be EQ or NE\n")));
res = 0;
}
else
int vala;
int valb;
int cond;
- idx = exp_get_abs ("Conditional operator must have absolute operands.\n", idx, in, &vala);
+ idx = exp_get_abs (_("Conditional operator must have absolute operands.\n"), idx, in, &vala);
idx = whatcond (idx, in, &cond);
idx = sb_skip_white (idx, in);
if (in->ptr[idx] == '"')
{
- WARNING ((stderr, "String compared against expression.\n"));
+ WARNING ((stderr, _("String compared against expression.\n")));
res = 0;
}
else
{
- idx = exp_get_abs ("Conditional operator must have absolute operands.\n", idx, in, &valb);
+ idx = exp_get_abs (_("Conditional operator must have absolute operands.\n"), idx, in, &valb);
switch (cond)
{
default:
{
if (ifi >= IFNESTING)
{
- FATAL ((stderr, "AIF nesting unreasonable.\n"));
+ FATAL ((stderr, _("AIF nesting unreasonable.\n")));
}
ifi++;
ifstack[ifi].on = ifstack[ifi-1].on ? istrue (idx, in) : 0;
ifstack[ifi].on = ifstack[ifi-1].on ? !ifstack[ifi].on : 0;
if (ifstack[ifi].hadelse)
{
- ERROR ((stderr, "Multiple AELSEs in AIF.\n"));
+ ERROR ((stderr, _("Multiple AELSEs in AIF.\n")));
}
ifstack[ifi].hadelse = 1;
}
}
else
{
- ERROR ((stderr, "AENDI without AIF.\n"));
+ ERROR ((stderr, _("AENDI without AIF.\n")));
}
}
return ifstack[ifi].on;
}
-
-/* Read input lines till we get to a TO string.
- Increase nesting depth if we geta FROM string.
- Put the results into sb at PTR. */
+/* MRI IFEQ, IFNE, IFLT, IFLE, IFGE, IFGT. */
static void
-buffer_and_nest (from, to, ptr)
- char *from;
- char *to;
- sb *ptr;
+do_if (idx, in, cond)
+ int idx;
+ sb *in;
+ int cond;
{
- int from_len = strlen (from);
- int to_len = strlen (to);
- int depth = 1;
- int line_start = ptr->len;
- int line = linecount ();
-
- int more = get_line (ptr);
+ int val;
+ int res;
- while (more)
+ if (ifi >= IFNESTING)
{
- /* Try and find the first pseudo op on the line */
- int i = line_start;
-
- if (!alternate)
- {
- /* 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 cant tell what's a label and whats a pseudoop */
-
- /* Skip leading whitespace */
- while (i < ptr->len
- && ISWHITE (ptr->ptr[i]))
- i++;
-
- /* Skip over a label */
- while (i < ptr->len
- && ISNEXTCHAR (ptr->ptr[i]))
- i++;
-
- /* And a colon */
- if (i < ptr->len
- && ptr->ptr[i] == ':')
- i++;
-
+ FATAL ((stderr, _("IF nesting unreasonable.\n")));
}
- /* Skip trailing whitespace */
- while (i < ptr->len
- && ISWHITE (ptr->ptr[i]))
- i++;
-
- if (i < ptr->len && (ptr->ptr[i] == '.'
- || alternate))
- {
- if (ptr->ptr[i] == '.')
- i++;
- if (strncasecmp (ptr->ptr + i, from, from_len) == 0)
- depth++;
- if (strncasecmp (ptr->ptr + i, to, to_len) == 0)
- {
- depth--;
- if (depth == 0)
- {
- /* Reset the string to not include the ending rune */
- ptr->len = line_start;
- break;
- }
- }
- }
- /* Add a CR to the end and keep running */
- sb_add_char (ptr, '\n');
- line_start = ptr->len;
- more = get_line (ptr);
+ idx = exp_get_abs (_("Conditional operator must have absolute operands.\n"),
+ idx, in, &val);
+ switch (cond)
+ {
+ default:
+ case EQ: res = val == 0; break;
+ case NE: res = val != 0; break;
+ case LT: res = val < 0; break;
+ case LE: res = val <= 0; break;
+ case GE: res = val >= 0; break;
+ case GT: res = val > 0; break;
}
-
- if (depth)
- FATAL ((stderr, "End of file whilst inside %s, started on line %d.\n", from, line));
+ ifi++;
+ ifstack[ifi].on = ifstack[ifi-1].on ? res: 0;
+ ifstack[ifi].hadelse = 0;
}
+/* Get a string for the MRI IFC or IFNC pseudo-ops. */
+
+static int
+get_mri_string (idx, in, val, terminator)
+ int idx;
+ sb *in;
+ sb *val;
+ int terminator;
+{
+ idx = sb_skip_white (idx, in);
+
+ if (idx < in->len
+ && in->ptr[idx] == '\'')
+ {
+ sb_add_char (val, '\'');
+ for (++idx; idx < in->len; ++idx)
+ {
+ sb_add_char (val, in->ptr[idx]);
+ if (in->ptr[idx] == '\'')
+ {
+ ++idx;
+ if (idx >= in->len
+ || in->ptr[idx] != '\'')
+ break;
+ }
+ }
+ idx = sb_skip_white (idx, in);
+ }
+ else
+ {
+ int i;
+
+ while (idx < in->len
+ && in->ptr[idx] != terminator)
+ {
+ sb_add_char (val, in->ptr[idx]);
+ ++idx;
+ }
+ i = val->len - 1;
+ while (i >= 0 && ISWHITE (val->ptr[i]))
+ --i;
+ val->len = i + 1;
+ }
+
+ return idx;
+}
+
+/* MRI IFC, IFNC. */
+
+static void
+do_ifc (idx, in, ifnc)
+ int idx;
+ sb *in;
+ int ifnc;
+{
+ sb first;
+ sb second;
+ int res;
+
+ if (ifi >= IFNESTING)
+ {
+ FATAL ((stderr, _("IF nesting unreasonable.\n")));
+ }
+
+ sb_new (&first);
+ sb_new (&second);
+
+ idx = get_mri_string (idx, in, &first, ',');
+
+ if (idx >= in->len || in->ptr[idx] != ',')
+ {
+ ERROR ((stderr, _("Bad format for IF or IFNC.\n")));
+ return;
+ }
+
+ idx = get_mri_string (idx + 1, in, &second, ';');
+
+ res = (first.len == second.len
+ && strncmp (first.ptr, second.ptr, first.len) == 0);
+ res ^= ifnc;
+
+ ifi++;
+ ifstack[ifi].on = ifstack[ifi-1].on ? res : 0;
+ ifstack[ifi].hadelse = 0;
+}
/* .ENDR */
-void
+static void
do_aendr ()
{
- ERROR ((stderr, "AENDR without a AREPEAT.\n"));
+ if (!mri)
+ ERROR ((stderr, _("AENDR without a AREPEAT.\n")));
+ else
+ ERROR ((stderr, _("ENDR without a REPT.\n")));
}
/* .AWHILE */
int idx;
sb *in;
{
+ int line = linecount ();
sb exp;
-
sb sub;
-
int doit;
+
sb_new (&sub);
sb_new (&exp);
process_assigns (idx, in, &exp);
doit = istrue (0, &exp);
- buffer_and_nest ("AWHILE", "AENDW", &sub);
+ if (! buffer_and_nest ("AWHILE", "AENDW", &sub, get_line))
+ FATAL ((stderr, _("AWHILE without a AENDW at %d.\n"), line - 1));
/* Turn
.AWHILE exp
static void
do_aendw ()
{
- ERROR ((stderr, "AENDW without a AENDW.\n"));
+ ERROR ((stderr, _("AENDW without a AENDW.\n")));
}
int idx;
sb *in;
{
+ int line = linecount ();
sb exp; /* buffer with expression in it */
sb copy; /* expanded repeat block */
sb sub; /* contents of AREPEAT */
int rc;
+ int ret;
char buffer[30];
+
sb_new (&exp);
sb_new (©);
sb_new (&sub);
process_assigns (idx, in, &exp);
- idx = exp_get_abs ("AREPEAT must have absolute operand.\n", 0, &exp, &rc);
- buffer_and_nest ("AREPEAT", "AENDR", &sub);
+ idx = exp_get_abs (_("AREPEAT must have absolute operand.\n"), 0, &exp, &rc);
+ if (!mri)
+ ret = buffer_and_nest ("AREPEAT", "AENDR", &sub, get_line);
+ else
+ ret = buffer_and_nest ("REPT", "ENDR", &sub, get_line);
+ if (! ret)
+ FATAL ((stderr, _("AREPEAT without a AENDR at %d.\n"), line - 1));
if (rc > 0)
{
/* Push back the text following the repeat, and another repeat block
sb_add_sb (©, &sub);
if (rc > 1)
{
- sprintf (buffer, "\t.AREPEAT %d\n", rc - 1);
+ if (!mri)
+ sprintf (buffer, "\t.AREPEAT %d\n", rc - 1);
+ else
+ sprintf (buffer, "\tREPT %d\n", rc - 1);
sb_add_string (©, buffer);
sb_add_sb (©, &sub);
- sb_add_string (©, " .AENDR\n");
+ if (!mri)
+ sb_add_string (©, " .AENDR\n");
+ else
+ sb_add_string (©, " ENDR\n");
}
include_buf (&exp, ©, include_repeat, index);
static void
do_endm ()
{
- ERROR ((stderr, ".ENDM without a matching .MACRO.\n"));
+ ERROR ((stderr, _(".ENDM without a matching .MACRO.\n")));
}
+/* MRI IRP pseudo-op. */
-/* MARRO PROCESSING */
-
-static int number;
-hash_table macro_table;
-
-/* Understand
-
- .MACRO <name>
- stuff
- .ENDM
-*/
-
-static int
-do_formals (macro, idx, in)
- macro_entry *macro;
+static void
+do_irp (idx, in, irpc)
int idx;
sb *in;
+ int irpc;
{
- formal_entry **p = ¯o->formals;
- macro->formal_count = 0;
- hash_new_table (5, ¯o->formal_hash);
- while (idx < in->len)
- {
- formal_entry *formal;
-
- formal = (formal_entry *) xmalloc (sizeof (formal_entry));
-
- sb_new (&formal->name);
- sb_new (&formal->def);
- sb_new (&formal->actual);
+ const char *err;
+ sb out;
- idx = sb_skip_white (idx, in);
- idx = get_token (idx, in, &formal->name);
- if (formal->name.len == 0)
- break;
- idx = sb_skip_white (idx, in);
- if (formal->name.len)
- {
- /* This is a formal */
- if (idx < in->len && in->ptr[idx] == '=')
- {
- /* Got a default */
- idx = get_any_string (idx + 1, in, &formal->def, 1, 0);
- }
- }
+ sb_new (&out);
- {
- /* Add to macro's hash table */
+ err = expand_irp (irpc, idx, in, &out, get_line, comment_char);
+ if (err != NULL)
+ ERROR ((stderr, "%s\n", err));
- hash_entry *p = hash_create (¯o->formal_hash, &formal->name);
- p->type = hash_formal;
- p->value.f = formal;
- }
+ fprintf (outfile, "%s", sb_terminate (&out));
- formal->index = macro->formal_count;
- idx = sb_skip_comma (idx, in);
- macro->formal_count++;
- *p = formal;
- p = &formal->next;
- }
- return idx;
+ sb_kill (&out);
}
+/* MACRO PROCESSING */
+
/* Parse off LOCAL n1, n2,... Invent a label name for it */
static
void
int idx;
sb *line;
{
- static int ln;
- sb acc;
- sb sub;
- char subs[10];
- sb_new (&acc);
- sb_new (&sub);
- idx = sb_skip_white (idx, line);
- while (!eol(idx, line))
- {
- sb_reset (&acc);
- sb_reset (&sub);
- ln++;
- sprintf(subs, "LL%04x", ln);
- idx = get_token(idx, line, &acc);
- sb_add_string (&sub, subs);
- hash_add_to_string_table (&assign_hash_table, &acc, &sub, 1);
- idx = sb_skip_comma (idx, line);
- }
- sb_kill (&sub);
- sb_kill (&acc);
+ ERROR ((stderr, _("LOCAL outside of MACRO")));
}
-static
-void
+static void
do_macro (idx, in)
int idx;
sb *in;
{
- macro_entry *macro;
- sb name;
-
- macro = (macro_entry *) xmalloc (sizeof (macro_entry));
- sb_new (¯o->sub);
- sb_new (&name);
-
- macro->formal_count = 0;
- macro->formals = 0;
-
- idx = sb_skip_white (idx, in);
- buffer_and_nest ("MACRO", "ENDM", ¯o->sub);
- if (label.len)
- {
-
- sb_add_sb (&name, &label);
- if (in->ptr[idx] == '(')
- {
- /* It's the label: MACRO (formals,...) sort */
- idx = do_formals (macro, idx + 1, in);
- if (in->ptr[idx] != ')')
- ERROR ((stderr, "Missing ) after formals.\n"));
- }
- else {
- /* It's the label: MACRO formals,... sort */
- idx = do_formals (macro, idx, in);
- }
- }
- else
- {
- idx = get_token (idx, in, &name);
- idx = sb_skip_white (idx, in);
- idx = do_formals (macro, idx, in);
- }
-
- /* and stick it in the macro hash table */
- hash_create (¯o_table, &name)->value.m = macro;
-}
-
-static
-int
-get_token (idx, in, name)
- int idx;
- sb *in;
- sb *name;
-{
- if (idx < in->len
- && ISFIRSTCHAR (in->ptr[idx]))
- {
- sb_add_char (name, in->ptr[idx++]);
- while (idx < in->len
- && ISNEXTCHAR (in->ptr[idx]))
- {
- sb_add_char (name, in->ptr[idx++]);
- }
- }
- /* Ignore trailing & */
- if (alternate && idx < in->len && in->ptr[idx] == '&')
- idx++;
- return idx;
-}
+ const char *err;
+ int line = linecount ();
-/* Scan a token, but stop if a ' is seen */
-static int
-get_apost_token (idx, in, name, kind)
- int idx;
- sb *in;
- sb *name;
- int kind;
-{
- idx = get_token (idx, in, name);
- if (idx < in->len && in->ptr[idx] == kind)
- idx++;
- return idx;
+ err = define_macro (idx, in, &label, get_line, (const char **) NULL);
+ if (err != NULL)
+ ERROR ((stderr, _("macro at line %d: %s\n"), line - 1, err));
}
static int
-sub_actual (src, in, t, m, kind, out, copyifnotthere)
- int src;
- sb *in;
- sb *t;
- macro_entry *m;
- int kind;
- sb *out;
- int copyifnotthere;
-{
- /* This is something to take care of */
- hash_entry *ptr;
- src = get_apost_token (src, in, t, kind);
- /* See if it's in the macro's hash table */
- ptr = hash_lookup (&m->formal_hash, t);
- if (ptr)
- {
- if (ptr->value.f->actual.len)
- {
- sb_add_sb (out, &ptr->value.f->actual);
- }
- else
- {
- sb_add_sb (out, &ptr->value.f->def);
- }
- }
- else if (copyifnotthere)
- {
- sb_add_sb (out, t);
- }
- else
- {
- sb_add_char (out, '\\');
- sb_add_sb (out, t);
- }
- return src;
-}
-
-static
-void
-macro_expand (name, idx, in, m)
- sb *name;
+macro_op (idx, in)
int idx;
sb *in;
- macro_entry *m;
{
- sb t;
+ const char *err;
sb out;
- hash_entry *ptr;
- formal_entry *f;
- int is_positional = 0;
- int is_keyword = 0;
-
- sb_new (&t);
- sb_new (&out);
-
- /* Reset any old value the actuals may have */
- for (f = m->formals; f; f = f->next)
- sb_reset (&f->actual);
- f = m->formals;
- /* Peel off the actuals and store them away in the hash tables' actuals */
- while (!eol(idx, in))
- {
- int scan;
- idx = sb_skip_white (idx, in);
- /* Look and see if it's a positional or keyword arg */
- scan = idx;
- while (scan < in->len
- && !ISSEP (in->ptr[scan])
- && (!alternate && in->ptr[scan] != '='))
- scan++;
- if (scan < in->len && (!alternate) && in->ptr[scan] == '=')
- {
- is_keyword = 1;
- if (is_positional)
- {
- ERROR ((stderr, "Can't mix positional and keyword arguments.\n"));
- return;
- }
- /* This is a keyword arg, fetch the formal name and
- then the actual stuff */
- sb_reset (&t);
- idx = get_token (idx, in, &t);
- if (in->ptr[idx] != '=')
- ERROR ((stderr, "confused about formal params.\n"));
-
- /* Lookup the formal in the macro's list */
- ptr = hash_lookup (&m->formal_hash, &t);
- if (!ptr)
- {
- ERROR ((stderr, "MACRO formal argument %s does not exist.\n", sb_name (&t)));
- return;
- }
- else
- {
- /* Insert this value into the right place */
- sb_reset (&ptr->value.f->actual);
- idx = get_any_string (idx + 1, in, &ptr->value.f->actual, 0, 0);
- }
- }
- else
- {
- /* This is a positional arg */
- is_positional = 1;
- if (is_keyword)
- {
- ERROR ((stderr, "Can't mix positional and keyword arguments.\n"));
- return;
- }
- if (!f)
- {
- ERROR ((stderr, "Too many positional arguments.\n"));
- return;
- }
+ sb name;
- sb_reset (&f->actual);
- idx = get_any_string (idx, in, &f->actual, 1, 0);
- f = f->next;
- }
- idx = sb_skip_comma (idx, in);
- }
+ if (! macro_defined)
+ return 0;
- /* Copy the stuff from the macro buffer into a safe place and substitute any args */
+ sb_terminate (in);
+ if (! check_macro (in->ptr + idx, &out, comment_char, &err))
+ return 0;
- {
- int src = 0;
- int inquote = 0;
- sb *in = &m->sub;
- sb_reset (&out);
+ if (err != NULL)
+ ERROR ((stderr, "%s\n", err));
- while (src < in->len)
- {
- if (in->ptr[src] == '&')
- {
- sb_reset (&t);
- src = sub_actual (src + 1, in, &t, m, '&', &out, 0);
- }
- else if (in->ptr[src] == '\\')
- {
- src++;
- if (in->ptr[src] == comment_char)
- {
- /* This is a comment, just drop the rest of the line */
- while (src < in->len
- && in->ptr[src] != '\n')
- src++;
+ sb_new (&name);
+ sb_add_string (&name, _("macro expansion"));
- }
- else if (in->ptr[src] == '(')
- {
- /* Sub in till the next ')' literally */
- src++;
- while (src < in->len && in->ptr[src] != ')')
- {
- sb_add_char (&out, in->ptr[src++]);
- }
- if (in->ptr[src] == ')')
- src++;
- else
- ERROR ((stderr, "Missplaced ).\n"));
- }
- else if (in->ptr[src] == '@')
- {
- /* Sub in the macro invocation number */
+ include_buf (&name, &out, include_macro, include_next_index ());
- char buffer[6];
- src++;
- sprintf (buffer, "%05d", number);
- sb_add_string (&out, buffer);
- }
- else if (in->ptr[src] == '&')
- {
- /* This is a preprocessor variable name, we don't do them
- here */
- sb_add_char (&out, '\\');
- sb_add_char (&out, '&');
- src++;
- }
- else
- {
- sb_reset (&t);
- src = sub_actual (src, in, &t, m, '\'', &out, 0);
- }
- }
- else if (ISFIRSTCHAR (in->ptr[src]) && alternate)
- {
- sb_reset (&t);
- src = sub_actual (src, in, &t, m, '\'', &out, 1);
- }
- else if (ISCOMMENTCHAR (in->ptr[src])
- && src + 1 < in->len
- && ISCOMMENTCHAR (in->ptr[src+1])
- && !inquote)
- {
- /* Two comment chars in a row cause the rest of the line to be dropped */
- while (src < in->len && in->ptr[src] != '\n')
- src++;
- }
- else if (in->ptr[src] == '"')
- {
- inquote = !inquote;
- sb_add_char (&out, in->ptr[src++]);
- }
- else
- {
- sb_add_char (&out, in->ptr[src++]);
- }
- }
- include_buf (name, &out, include_macro, include_next_index ());
- }
- sb_kill (&t);
+ sb_kill (&name);
sb_kill (&out);
- number++;
-}
-
-static int
-macro_op (idx, in)
- int idx;
- sb *in;
-{
- int res = 0;
- /* The macro name must be the first thing on the line */
- if (idx < in->len)
- {
- sb name;
- hash_entry *ptr;
- sb_new (&name);
- idx = get_token (idx, in, &name);
-
- if (name.len)
- {
- /* Got a name, look it up */
- ptr = hash_lookup (¯o_table, &name);
-
- if (ptr)
- {
- /* It's in the table, copy out the stuff and convert any macro args */
- macro_expand (&name, idx, in, ptr->value.m);
- res = 1;
- }
- }
- sb_kill (&name);
- }
-
-
- return res;
+ return 1;
}
-
/* STRING HANDLING */
static int
{
if (in->ptr[idx] == '<')
{
- if (alternate)
+ if (alternate || mri)
{
int nest = 0;
idx++;
else {
int code;
idx++;
- idx = exp_get_abs ("Character code in string must be absolute expression.\n",
+ idx = exp_get_abs (_("Character code in string must be absolute expression.\n"),
idx, in, &code);
sb_add_char (acc, code);
if (in->ptr[idx] != '>')
- ERROR ((stderr, "Missing > for character code.\n"));
+ ERROR ((stderr, _("Missing > for character code.\n")));
idx++;
}
}
do_sdata (idx, in, type)
int idx;
sb *in;
- char type;
+ int type;
{
int nc = 0;
int pidx = -1;
{
if (acc.len > 255)
{
- ERROR ((stderr, "string for SDATAC longer than 255 characters (%d).\n", acc.len));
+ ERROR ((stderr, _("string for SDATAC longer than 255 characters (%d).\n"), acc.len));
}
fprintf (outfile, "%d", acc.len);
nc = 1;
if (!alternate && in->ptr[idx] != ',' && idx != in->len)
{
fprintf (outfile, "\n");
- ERROR ((stderr, "illegal character in SDATA line (0x%x).\n", in->ptr[idx]));
+ ERROR ((stderr, _("illegal character in SDATA line (0x%x).\n"), in->ptr[idx]));
break;
}
idx++;
sb acc;
sb_new (&acc);
- idx = exp_get_abs ("Must have absolute SDATAB repeat count.\n", idx, in, &repeat);
+ idx = exp_get_abs (_("Must have absolute SDATAB repeat count.\n"), idx, in, &repeat);
if (repeat <= 0)
{
- ERROR ((stderr, "Must have positive SDATAB repeat count (%d).\n", repeat));
+ ERROR ((stderr, _("Must have positive SDATAB repeat count (%d).\n"), repeat));
repeat = 1;
}
if (i)
fprintf (outfile, "\t");
fprintf (outfile, ".byte\t");
- sb_print (&acc);
+ sb_print (outfile, &acc);
fprintf (outfile, "\n");
}
sb_kill (&acc);
}
-int
+static int
new_file (name)
- char *name;
+ const char *name;
{
FILE *newone = fopen (name, "r");
if (!newone)
return 0;
if (isp == MAX_INCLUDES)
- FATAL ((stderr, "Unreasonable include depth (%ld).\n", (long) isp));
+ FATAL ((stderr, _("Unreasonable include depth (%ld).\n"), (long) isp));
sp++;
sp->handle = newone;
sb *in;
{
sb t;
- char *text;
+ sb cat;
+ include_path *includes;
+
sb_new (&t);
- idx = getstring (idx, in, &t);
- text = sb_name (&t);
- if (!new_file (text))
+ sb_new (&cat);
+
+ if (! mri)
+ idx = getstring (idx, in, &t);
+ else
+ {
+ idx = sb_skip_white (idx, in);
+ while (idx < in->len && ! ISWHITE (in->ptr[idx]))
+ {
+ sb_add_char (&t, in->ptr[idx]);
+ ++idx;
+ }
+ }
+
+ for (includes = paths_head; includes; includes = includes->next)
+ {
+ sb_reset (&cat);
+ sb_add_sb (&cat, &includes->path);
+ sb_add_char (&cat, '/');
+ sb_add_sb (&cat, &t);
+ if (new_file (sb_name (&cat)))
+ {
+ break;
+ }
+ }
+ if (!includes)
{
- FATAL ((stderr, "Can't open include file `%s'.\n", text));
+ if (! new_file (sb_name (&t)))
+ FATAL ((stderr, _("Can't open include file `%s'.\n"), sb_name (&t)));
}
+ sb_kill (&cat);
sb_kill (&t);
}
static int index;
if (!unreasonable
&& index > MAX_REASONABLE)
- FATAL ((stderr, "Unreasonable expansion (-u turns off check).\n"));
+ FATAL ((stderr, _("Unreasonable expansion (-u turns off check).\n")));
return ++index;
}
if (isalpha (x) || x == '_' || x == '$')
chartype[x] |= FIRSTBIT;
+ if (mri && x == '.')
+ chartype[x] |= FIRSTBIT;
+
if (isdigit (x) || isalpha (x) || x == '_' || x == '$')
chartype[x] |= NEXTBIT;
#define PROCESS 0x1000 /* Run substitution over the line */
#define LAB 0x2000 /* Spit out the label */
-#define K_EQU PROCESS|1
-#define K_ASSIGN PROCESS|2
-#define K_REG PROCESS|3
-#define K_ORG PROCESS|4
-#define K_RADIX PROCESS|5
-#define K_DATA LAB|PROCESS|6
-#define K_DATAB LAB|PROCESS|7
-#define K_SDATA LAB|PROCESS|8
-#define K_SDATAB LAB|PROCESS|9
-#define K_SDATAC LAB|PROCESS|10
-#define K_SDATAZ LAB|PROCESS|11
-#define K_RES LAB|PROCESS|12
-#define K_SRES LAB|PROCESS|13
-#define K_SRESC LAB|PROCESS|14
-#define K_SRESZ LAB|PROCESS|15
-#define K_EXPORT LAB|PROCESS|16
-#define K_GLOBAL LAB|PROCESS|17
-#define K_PRINT LAB|PROCESS|19
-#define K_FORM LAB|PROCESS|20
-#define K_HEADING LAB|PROCESS|21
-#define K_PAGE LAB|PROCESS|22
-#define K_IMPORT LAB|PROCESS|23
-#define K_PROGRAM LAB|PROCESS|24
-#define K_END PROCESS|25
-#define K_INCLUDE PROCESS|26
-#define K_IGNORED PROCESS|27
-#define K_ASSIGNA PROCESS|28
-#define K_ASSIGNC 29
-#define K_AIF PROCESS|30
-#define K_AELSE PROCESS|31
-#define K_AENDI PROCESS|32
-#define K_AREPEAT PROCESS|33
-#define K_AENDR PROCESS|34
-#define K_AWHILE 35
-#define K_AENDW PROCESS|36
-#define K_EXITM 37
-#define K_MACRO PROCESS|38
-#define K_ENDM 39
-#define K_ALIGN PROCESS|LAB|40
-#define K_ALTERNATE 41
-#define K_DB LAB|PROCESS|42
-#define K_DW LAB|PROCESS|43
-#define K_DL LAB|PROCESS|44
-#define K_LOCAL 45
-
-
-static struct
+#define K_EQU (PROCESS|1)
+#define K_ASSIGN (PROCESS|2)
+#define K_REG (PROCESS|3)
+#define K_ORG (PROCESS|4)
+#define K_RADIX (PROCESS|5)
+#define K_DATA (LAB|PROCESS|6)
+#define K_DATAB (LAB|PROCESS|7)
+#define K_SDATA (LAB|PROCESS|8)
+#define K_SDATAB (LAB|PROCESS|9)
+#define K_SDATAC (LAB|PROCESS|10)
+#define K_SDATAZ (LAB|PROCESS|11)
+#define K_RES (LAB|PROCESS|12)
+#define K_SRES (LAB|PROCESS|13)
+#define K_SRESC (LAB|PROCESS|14)
+#define K_SRESZ (LAB|PROCESS|15)
+#define K_EXPORT (LAB|PROCESS|16)
+#define K_GLOBAL (LAB|PROCESS|17)
+#define K_PRINT (LAB|PROCESS|19)
+#define K_FORM (LAB|PROCESS|20)
+#define K_HEADING (LAB|PROCESS|21)
+#define K_PAGE (LAB|PROCESS|22)
+#define K_IMPORT (LAB|PROCESS|23)
+#define K_PROGRAM (LAB|PROCESS|24)
+#define K_END (PROCESS|25)
+#define K_INCLUDE (PROCESS|26)
+#define K_IGNORED (PROCESS|27)
+#define K_ASSIGNA (PROCESS|28)
+#define K_ASSIGNC (29)
+#define K_AIF (PROCESS|30)
+#define K_AELSE (PROCESS|31)
+#define K_AENDI (PROCESS|32)
+#define K_AREPEAT (PROCESS|33)
+#define K_AENDR (PROCESS|34)
+#define K_AWHILE (35)
+#define K_AENDW (PROCESS|36)
+#define K_EXITM (37)
+#define K_MACRO (PROCESS|38)
+#define K_ENDM (39)
+#define K_ALIGN (PROCESS|LAB|40)
+#define K_ALTERNATE (41)
+#define K_DB (LAB|PROCESS|42)
+#define K_DW (LAB|PROCESS|43)
+#define K_DL (LAB|PROCESS|44)
+#define K_LOCAL (45)
+#define K_IFEQ (PROCESS|46)
+#define K_IFNE (PROCESS|47)
+#define K_IFLT (PROCESS|48)
+#define K_IFLE (PROCESS|49)
+#define K_IFGE (PROCESS|50)
+#define K_IFGT (PROCESS|51)
+#define K_IFC (PROCESS|52)
+#define K_IFNC (PROCESS|53)
+#define K_IRP (PROCESS|54)
+#define K_IRPC (PROCESS|55)
+
+
+struct keyword
{
char *name;
int code;
int extra;
-}
-kinfo[] =
+};
+
+static struct keyword kinfo[] =
{
{ "EQU", K_EQU, 0 },
{ "ALTERNATE", K_ALTERNATE, 0 },
{ NULL, 0, 0 }
};
+/* Although the conditional operators are handled by gas, we need to
+ handle them here as well, in case they are used in a recursive
+ macro to end the recursion. */
+
+static struct keyword mrikinfo[] =
+{
+ { "IFEQ", K_IFEQ, 0 },
+ { "IFNE", K_IFNE, 0 },
+ { "IFLT", K_IFLT, 0 },
+ { "IFLE", K_IFLE, 0 },
+ { "IFGE", K_IFGE, 0 },
+ { "IFGT", K_IFGT, 0 },
+ { "IFC", K_IFC, 0 },
+ { "IFNC", K_IFNC, 0 },
+ { "ELSEC", K_AELSE, 0 },
+ { "ENDC", K_AENDI, 0 },
+ { "MEXIT", K_EXITM, 0 },
+ { "REPT", K_AREPEAT, 0 },
+ { "IRP", K_IRP, 0 },
+ { "IRPC", K_IRPC, 0 },
+ { "ENDR", K_AENDR, 0 },
+ { NULL, 0, 0 }
+};
+
/* Look for a pseudo op on the line. If one's there then call
its handler. */
sb *line;
sb *acc;
{
+ int oidx = idx;
-
- if (line->ptr[idx] == '.' || alternate)
+ if (line->ptr[idx] == '.' || alternate || mri)
{
/* Scan forward and find pseudo name */
char *in;
#if 0
/* This one causes lots of pain when trying to preprocess
ordinary code */
- WARNING ((stderr, "Unrecognised pseudo op `%s'.\n", sb_name (acc)));
+ WARNING ((stderr, _("Unrecognised pseudo op `%s'.\n"), sb_name (acc)));
#endif
return 0;
}
fprintf (outfile, "\t");
}
+ if (mri && ptr->value.i == K_END)
+ {
+ sb t;
+
+ sb_new (&t);
+ sb_add_buffer (&t, line->ptr + oidx, idx - oidx);
+ fprintf (outfile, "\t%s", sb_name (&t));
+ sb_kill (&t);
+ }
+
if (ptr->value.i & PROCESS)
{
/* Polish the rest of the line before handling the pseudo op */
{
case K_ALTERNATE:
alternate = 1;
+ macro_init (1, mri, 0, exp_get_abs);
return 1;
case K_AELSE:
do_aelse ();
do_aendi ();
return 1;
case K_ORG:
- ERROR ((stderr, "ORG command not allowed.\n"));
+ ERROR ((stderr, _("ORG command not allowed.\n")));
break;
case K_RADIX:
do_radix (line);
do_sdata (idx, line, 'z');
return 1;
case K_ASSIGN:
- do_assign (1, 0, line);
+ do_assign (0, 0, line);
return 1;
case K_AIF:
do_aif (idx, line);
do_aendr ();
return 1;
case K_EQU:
- do_assign (0, idx, line);
+ do_assign (1, idx, line);
return 1;
case K_ALIGN:
do_align (idx, line);
case K_IGNORED:
return 1;
case K_END:
- do_end ();
+ do_end (line);
return 1;
case K_ASSIGNA:
do_assigna (idx, line);
case K_REG:
do_reg (idx, line);
return 1;
+ case K_IFEQ:
+ do_if (idx, line, EQ);
+ return 1;
+ case K_IFNE:
+ do_if (idx, line, NE);
+ return 1;
+ case K_IFLT:
+ do_if (idx, line, LT);
+ return 1;
+ case K_IFLE:
+ do_if (idx, line, LE);
+ return 1;
+ case K_IFGE:
+ do_if (idx, line, GE);
+ return 1;
+ case K_IFGT:
+ do_if (idx, line, GT);
+ return 1;
+ case K_IFC:
+ do_ifc (idx, line, 0);
+ return 1;
+ case K_IFNC:
+ do_ifc (idx, line, 1);
+ return 1;
+ case K_IRP:
+ do_irp (idx, line, 0);
+ return 1;
+ case K_IRPC:
+ do_irp (idx, line, 1);
+ return 1;
}
}
}
+/* Add a keyword to the hash table. */
+
+static void
+add_keyword (name, code)
+ const char *name;
+ int code;
+{
+ sb label;
+ int j;
+
+ sb_new (&label);
+ sb_add_string (&label, name);
+
+ hash_add_to_int_table (&keyword_hash_table, &label, code);
+
+ sb_reset (&label);
+ for (j = 0; name[j]; j++)
+ sb_add_char (&label, name[j] - 'A' + 'a');
+ hash_add_to_int_table (&keyword_hash_table, &label, code);
+
+ sb_kill (&label);
+}
+
/* Build the keyword hash table - put each keyword in the table twice,
once upper and once lower case.*/
int i;
for (i = 0; kinfo[i].name; i++)
- {
- sb label;
- int j;
- sb_new (&label);
- sb_add_string (&label, kinfo[i].name);
-
- hash_add_to_int_table (&keyword_hash_table, &label, kinfo[i].code);
+ add_keyword (kinfo[i].name, kinfo[i].code);
- sb_reset (&label);
- for (j = 0; kinfo[i].name[j]; j++)
- sb_add_char (&label, kinfo[i].name[j] - 'A' + 'a');
- hash_add_to_int_table (&keyword_hash_table, &label, kinfo[i].code);
-
- sb_kill (&label);
+ if (mri)
+ {
+ for (i = 0; mrikinfo[i].name; i++)
+ add_keyword (mrikinfo[i].name, mrikinfo[i].code);
}
}
static void
do_define (string)
-char *string;
+ const char *string;
{
sb label;
int res = 1;
sb_add_char (&value, *string);
string++;
}
- exp_get_abs ("Invalid expression on command line.\n", 0, &value, &res);
+ exp_get_abs (_("Invalid expression on command line.\n"), 0, &value, &res);
sb_kill (&value);
break;
}
static struct option long_options[] =
{
{ "alternate", no_argument, 0, 'a' },
+ { "include", required_argument, 0, 'I' },
{ "commentchar", required_argument, 0, 'c' },
{ "copysource", no_argument, 0, 's' },
{ "debug", no_argument, 0, 'd' },
{ "help", no_argument, 0, 'h' },
+ { "mri", no_argument, 0, 'M' },
{ "output", required_argument, 0, 'o' },
{ "print", no_argument, 0, 'p' },
{ "unreasonable", no_argument, 0, 'u' },
FILE *file;
int status;
{
- fprintf (file, "\
+ fprintf (file, _("\
Usage: %s \n\
[-a] [--alternate] enter alternate macro mode\n\
[-c char] [--commentchar char] change the comment character from !\n\
[-d] [--debug] print some debugging info\n\
[-h] [--help] print this message\n\
+ [-M] [--mri] enter MRI compatibility mode\n\
[-o out] [--output out] set the output file\n\
- [-p] [--print] print line numbers\n\
+ [-p] [--print] print line numbers\n"), program_name);
+ fprintf (file, _("\
[-s] [--copysource] copy source through as comments \n\
[-u] [--unreasonable] allow unreasonable nesting\n\
[-v] [--version] print the program version\n\
[-Dname=value] create preprocessor variable called name, with value\n\
- [in-file]\n", program_name);
+ [-Ipath] add to include path list\n\
+ [in-file]\n"));
+ if (status == 0)
exit (status);
}
static void
show_help ()
{
- printf ("%s: Gnu Assembler Macro Preprocessor\n",
+ printf (_("%s: Gnu Assembler Macro Preprocessor\n"),
program_name);
show_usage (stdout, 0);
}
ifstack[0].on = 1;
ifi = 0;
-
+#ifdef HAVE_SETLOCALE
+ setlocale (LC_MESSAGES, "");
+#endif
+ bindtextdomain (PACKAGE, LOCALEDIR);
+ textdomain (PACKAGE);
program_name = argv[0];
xmalloc_set_program_name (program_name);
- hash_new_table (101, ¯o_table);
hash_new_table (101, &keyword_hash_table);
hash_new_table (101, &assign_hash_table);
hash_new_table (101, &vars);
sb_new (&label);
- process_init ();
- while ((opt = getopt_long (argc, argv, "sdhavc:upo:D:", long_options,
+ while ((opt = getopt_long (argc, argv, "I:sdhavc:upo:D:M", long_options,
(int *) NULL))
!= EOF)
{
case 'u':
unreasonable = 1;
break;
+ case 'I':
+ {
+ include_path *p = (include_path *) xmalloc (sizeof (include_path));
+ p->next = NULL;
+ sb_new (&p->path);
+ sb_add_string (&p->path, optarg);
+ if (paths_tail)
+ paths_tail->next = p;
+ else
+ paths_head = p;
+ paths_tail = p;
+ }
+ break;
case 'p':
print_line_number = 1;
break;
case 'D':
do_define (optarg);
break;
+ case 'M':
+ mri = 1;
+ comment_char = ';';
+ break;
case 'h':
show_help ();
/*NOTREACHED*/
case 'v':
- printf ("GNU %s version %s\n", program_name, program_version);
+ /* This output is intended to follow the GNU standards document. */
+ printf (_("GNU assembler pre-processor %s\n"), program_version);
+ printf (_("Copyright 1996 Free Software Foundation, Inc.\n"));
+ printf (_("\
+This program is free software; you may redistribute it under the terms of\n\
+the GNU General Public License. This program has absolutely no warranty.\n"));
exit (0);
/*NOTREACHED*/
case 0:
}
}
+ process_init ();
+
+ macro_init (alternate, mri, 0, exp_get_abs);
if (out_name) {
outfile = fopen (out_name, "w");
if (!outfile)
{
- fprintf (stderr, "%s: Can't open output file `%s'.\n",
+ fprintf (stderr, _("%s: Can't open output file `%s'.\n"),
program_name, out_name);
exit (1);
}
}
else
{
- fprintf (stderr, "%s: Can't open input file `%s'.\n",
+ fprintf (stderr, _("%s: Can't open input file `%s'.\n"),
program_name, argv[optind]);
exit (1);
}
quit ();
return 0;
}
+
+/* This function is used because an abort in some of the other files
+ may be compiled into as_abort because they include as.h. */
+
+void
+as_abort (file, line, fn)
+ const char *file, *fn;
+ int line;
+{
+ fprintf (stderr, _("Internal error, aborting at %s line %d"), file, line);
+ if (fn)
+ fprintf (stderr, " in %s", fn);
+ fprintf (stderr, _("\nPlease report this bug.\n"));
+ exit (1);
+}