X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gas%2Fgasp.c;h=a8f56192aeeb3cb96568d74713373347274b6a85;hb=4b14d3e4e0d9ba2ff2f9397312f884f8fc9a1135;hp=3d1f588d573b7a3b3e58f71681f7af7333f735bb;hpb=4f2f30116bbef513af63b7b45bd7ef13bd7b4673;p=deliverable%2Fbinutils-gdb.git diff --git a/gas/gasp.c b/gas/gasp.c index 3d1f588d57..a8f56192ae 100644 --- a/gas/gasp.c +++ b/gas/gasp.c @@ -1,5 +1,6 @@ /* gasp.c - Gnu assembler preprocessor main program. - Copyright (C) 1994 Free Software Foundation, Inc. + Copyright (C) 1994, 95, 96, 97, 98, 99, 2000 + Free Software Foundation, Inc. Written by Steve and Judy Chamberlain of Cygnus Support, sac@cygnus.com @@ -17,8 +18,9 @@ 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. */ /* @@ -48,6 +50,7 @@ suitable for gas to consume. */ #include "config.h" +#include "bin-bugs.h" #include #include @@ -62,10 +65,24 @@ suitable for gas to consume. 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 *)); + +/* The default obstack chunk size. If we set this to zero, the + obstack code will use whatever will fit in a 4096 byte block. This + is used by the hash table code used by macro.c. */ +int chunksize = 0; + #define MAX_INCLUDES 30 /* Maximum include depth */ #define MAX_REASONABLE 1000 /* Maximum number of expansions */ @@ -77,6 +94,7 @@ int warnings; /* Number of WARNINGs generated so far. */ 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 */ @@ -85,72 +103,6 @@ int had_end; /* Seen .END */ /* 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<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. */ @@ -682,7 +452,7 @@ hash_add_to_string_table (tab, key, name, again) if (ptr->value.s.len) { if (!again) - ERROR ((stderr, "redefintion not allowed")); + ERROR ((stderr, _("redefinition not allowed\n"))); } ptr->type = hash_string; @@ -750,13 +520,13 @@ hash_lookup (tab, key) 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)); } } @@ -798,9 +568,7 @@ sb_strtol (idx, string, base, ptr) return idx; } -static int level_5 (); - -int +static int level_0 (idx, string, lhs) int idx; sb *string; @@ -816,7 +584,7 @@ level_0 (idx, string, lhs) lhs->value = 0; - if (isdigit (string->ptr[idx])) + if (isdigit ((unsigned char) string->ptr[idx])) { idx = sb_strtol (idx, string, 10, &lhs->value); } @@ -835,13 +603,13 @@ level_0 (idx, string, lhs) { 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); @@ -881,7 +649,7 @@ level_1 (idx, string, lhs) 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; @@ -918,7 +686,7 @@ level_2 (idx, string, lhs) 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; @@ -950,7 +718,7 @@ level_3 (idx, string, lhs) 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) @@ -1088,7 +856,7 @@ exp_string (exp, string) static int exp_get_abs (emsg, idx, in, val) - char *emsg; + const char *emsg; int idx; sb *in; int *val; @@ -1096,7 +864,7 @@ exp_get_abs (emsg, idx, in, val) exp_t res; idx = exp_parse (idx, in, &res); if (res.add_symbol.len || res.sub_symbol.len) - ERROR ((stderr, emsg)); + ERROR ((stderr, "%s", emsg)); *val = res.value; return idx; } @@ -1109,8 +877,8 @@ hash_table vars; /* hash table for eq variables */ #define in_comment ';' -#if 1 -void +#if 0 +static void strip_comments (out) sb *out; { @@ -1129,7 +897,7 @@ strip_comments (out) /* push back character ch so that it can be read again. */ -void +static void unget (ch) int ch; { @@ -1155,7 +923,7 @@ include_buf (name, ptr, type, index) { 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; @@ -1178,7 +946,7 @@ include_print_where_line (file) 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++; } } @@ -1233,7 +1001,7 @@ get_line (in) { 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'; @@ -1288,7 +1056,7 @@ grab_label (in, out) { 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++; @@ -1317,7 +1085,21 @@ change_base (idx, in, out) 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; @@ -1340,7 +1122,7 @@ change_base (idx, in, out) 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; } @@ -1360,7 +1142,7 @@ change_base (idx, in, out) 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 @@ -1400,9 +1182,12 @@ change_base (idx, in, out) /* .end */ static void -do_end () +do_end (in) + sb *in; { had_end = 1; + if (mri) + fprintf (outfile, "%s\n", sb_name (in)); } /* .assign */ @@ -1452,7 +1237,7 @@ do_radix (ptr) 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)); } } @@ -1461,9 +1246,9 @@ do_radix (ptr) 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] == '.') @@ -1488,7 +1273,7 @@ int *size; 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++; @@ -1498,8 +1283,8 @@ int *size; static int eol(idx, line) -int idx; -sb *line; + int idx; + sb *line; { idx = sb_skip_white (idx, line); if (idx < line->len @@ -1570,7 +1355,7 @@ do_data (idx, in, size) idx = exp_parse (idx, in, &e); exp_string (&e, &acc); sb_add_char (&acc, 0); - fprintf (outfile, acc.ptr); + fprintf (outfile, "%s", acc.ptr); if (idx < in->len && in->ptr[idx] == ',') { fprintf (outfile, ","); @@ -1579,7 +1364,7 @@ do_data (idx, in, size) } } sb_kill (&acc); - sb_print_at (idx, in); + sb_print_at (outfile, idx, in); fprintf (outfile, "\n"); } @@ -1596,38 +1381,47 @@ do_datab (idx, in) 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 */ -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; - if (al != 1 - && al != 2 - && al != 4) - WARNING ((stderr, "alignment must be one of 1, 2 or 4.\n")); + 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; + } - 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] */ -void +static void do_res (idx, in, type) int idx; sb *in; - char type; + int type; { int size = 4; int count = 0; @@ -1638,7 +1432,7 @@ do_res (idx, in, type) 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++; @@ -1650,7 +1444,7 @@ do_res (idx, in, type) /* .export */ -void +static void do_export (in) sb *in; { @@ -1659,7 +1453,7 @@ do_export (in) /* .print [list] [nolist] */ -void +static void do_print (idx, in) int idx; sb *in; @@ -1682,7 +1476,7 @@ do_print (idx, in) } /* .head */ -void +static void do_heading (idx, in) int idx; sb *in; @@ -1696,14 +1490,14 @@ do_heading (idx, in) /* .page */ -void +static void do_page () { fprintf (outfile, ".eject\n"); } /* .form [lin=] [col=] */ -void +static void do_form (idx, in) int idx; sb *in; @@ -1718,13 +1512,13 @@ do_form (idx, 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++; @@ -1741,7 +1535,7 @@ do_form (idx, in) "" -> return string xyx -> return xyz */ -int +static int get_any_string (idx, in, out, expand, pretend_quoted) int idx; sb *in; @@ -1766,7 +1560,7 @@ get_any_string (idx, in, out, expand, pretend_quoted) 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); @@ -1780,10 +1574,10 @@ get_any_string (idx, in, out, expand, pretend_quoted) 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 { @@ -1821,14 +1615,14 @@ get_any_string (idx, in, out, expand, pretend_quoted) /* 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; } @@ -1836,21 +1630,21 @@ skip_openp (idx, in) /* 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; @@ -1895,9 +1689,9 @@ doinstr (idx, in, out) 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 { @@ -1935,9 +1729,9 @@ dosubstr (idx, in, out) 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); @@ -1962,7 +1756,7 @@ dosubstr (idx, in, out) } /* scan line, change tokens in the hash table to their replacements */ -void +static void process_assigns (idx, in, buf) int idx; sb *in; @@ -1972,11 +1766,24 @@ process_assigns (idx, in, buf) { 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); @@ -2076,23 +1883,54 @@ process_file () if (condass_on ()) fprintf (outfile, "\n"); } + else if (mri + && (line.ptr[0] == '*' + || line.ptr[0] == '!')) + { + /* MRI line comment. */ + fprintf (outfile, "%s", 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)) @@ -2141,8 +1979,8 @@ process_file () 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"))); } @@ -2162,7 +2000,7 @@ free_old_entry (ptr) /* name: .ASSIGNA */ -void +static void do_assigna (idx, in) int idx; sb *in; @@ -2172,11 +2010,11 @@ do_assigna (idx, 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 { @@ -2190,7 +2028,7 @@ do_assigna (idx, in) /* name: .ASSIGNC */ -void +static void do_assignc (idx, in) int idx; sb *in; @@ -2201,7 +2039,7 @@ do_assignc (idx, in) if (!label.len) { - ERROR ((stderr, ".ASSIGNS without label.\n")); + ERROR ((stderr, _(".ASSIGNS without label.\n"))); } else { @@ -2224,9 +2062,15 @@ do_reg (idx, in) { /* 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++; @@ -2262,7 +2106,7 @@ condass_lookup_name (inbuf, idx, out, warn) { 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 { @@ -2294,7 +2138,7 @@ condass_lookup_name (inbuf, idx, out, warn) #define GT 6 #define NEVER 7 -int +static int whatcond (idx, in, val) int idx; sb *in; @@ -2327,7 +2171,7 @@ whatcond (idx, in, val) } 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); @@ -2335,7 +2179,7 @@ whatcond (idx, in, val) return idx; } -int +static int istrue (idx, in) int idx; sb *in; @@ -2361,7 +2205,7 @@ istrue (idx, 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 @@ -2373,17 +2217,17 @@ istrue (idx, in) 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: @@ -2428,7 +2272,7 @@ do_aif (idx, in) { 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; @@ -2443,7 +2287,7 @@ do_aelse () 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; } @@ -2459,7 +2303,7 @@ do_aendi () } else { - ERROR ((stderr, "AENDI without AIF.\n")); + ERROR ((stderr, _("AENDI without AIF.\n"))); } } @@ -2469,93 +2313,134 @@ condass_on () 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 val; + int res; - int more = get_line (ptr); + if (ifi >= IFNESTING) + { + FATAL ((stderr, _("IF nesting unreasonable.\n"))); + } - while (more) + idx = exp_get_abs (_("Conditional operator must have absolute operands.\n"), + idx, in, &val); + switch (cond) { - /* Try and find the first pseudo op on the line */ - int i = line_start; + 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 (!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 */ + ifi++; + ifstack[ifi].on = ifstack[ifi-1].on ? res: 0; + ifstack[ifi].hadelse = 0; +} - /* Skip leading whitespace */ - while (i < ptr->len - && ISWHITE (ptr->ptr[i])) - i++; +/* Get a string for the MRI IFC or IFNC pseudo-ops. */ - /* Skip over a label */ - while (i < ptr->len - && ISNEXTCHAR (ptr->ptr[i])) - i++; - - /* And a colon */ - if (i < ptr->len - && ptr->ptr[i] == ':') - i++; - - } - /* Skip trailing whitespace */ - while (i < ptr->len - && ISWHITE (ptr->ptr[i])) - i++; +static int +get_mri_string (idx, in, val, terminator) + int idx; + sb *in; + sb *val; + int terminator; +{ + idx = sb_skip_white (idx, in); - if (i < ptr->len && (ptr->ptr[i] == '.' - || alternate)) + if (idx < in->len + && in->ptr[idx] == '\'') + { + sb_add_char (val, '\''); + for (++idx; idx < in->len; ++idx) { - if (ptr->ptr[i] == '.') - i++; - if (strncasecmp (ptr->ptr + i, from, from_len) == 0) - depth++; - if (strncasecmp (ptr->ptr + i, to, to_len) == 0) + sb_add_char (val, in->ptr[idx]); + if (in->ptr[idx] == '\'') { - depth--; - if (depth == 0) - { - /* Reset the string to not include the ending rune */ - ptr->len = line_start; - break; - } + ++idx; + if (idx >= in->len + || in->ptr[idx] != '\'') + break; } } - - /* Add a CR to the end and keep running */ - sb_add_char (ptr, '\n'); - line_start = ptr->len; - more = get_line (ptr); + 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; + } - if (depth) - FATAL ((stderr, "End of file whilst inside %s, started on line %d.\n", from, line)); + 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 */ @@ -2566,18 +2451,19 @@ do_awhile (idx, in) 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 @@ -2615,7 +2501,7 @@ do_awhile (idx, in) static void do_aendw () { - ERROR ((stderr, "AENDW without a AENDW.\n")); + ERROR ((stderr, _("AENDW without a AENDW.\n"))); } @@ -2648,17 +2534,25 @@ do_arepeat (idx, in) 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 @@ -2676,10 +2570,16 @@ do_arepeat (idx, in) 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); @@ -2694,434 +2594,86 @@ do_arepeat (idx, in) 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 - 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; + const char *err; + sb out; - formal = (formal_entry *) xmalloc (sizeof (formal_entry)); + sb_new (&out); - sb_new (&formal->name); - sb_new (&formal->def); - sb_new (&formal->actual); + err = expand_irp (irpc, idx, in, &out, get_line, comment_char); + if (err != NULL) + ERROR ((stderr, "%s\n", err)); - 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); - } - } - - { - /* Add to macro's hash table */ + fprintf (outfile, "%s", sb_terminate (&out)); - hash_entry *p = hash_create (¯o->formal_hash, &formal->name); - p->type = hash_formal; - p->value.f = formal; - } - - 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 do_local (idx, line) - int idx; - sb *line; + int idx ATTRIBUTE_UNUSED; + sb *line ATTRIBUTE_UNUSED; { - 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; -} + const char *err; + int line = linecount (); -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; + 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)); } -/* 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; -} - -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, NULL)) + 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 @@ -3139,7 +2691,7 @@ getstring (idx, in, acc) { if (in->ptr[idx] == '<') { - if (alternate) + if (alternate || mri) { int nest = 0; idx++; @@ -3164,12 +2716,12 @@ getstring (idx, in, acc) 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++; } } @@ -3208,7 +2760,7 @@ void do_sdata (idx, in, type) int idx; sb *in; - char type; + int type; { int nc = 0; int pidx = -1; @@ -3228,7 +2780,7 @@ do_sdata (idx, in, type) { 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; @@ -3256,7 +2808,7 @@ do_sdata (idx, in, type) 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++; @@ -3277,10 +2829,10 @@ do_sdatab (idx, in) 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; } @@ -3292,23 +2844,23 @@ do_sdatab (idx, in) 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; @@ -3331,12 +2883,22 @@ do_include (idx, in) { sb t; sb cat; - char *text; include_path *includes; + sb_new (&t); sb_new (&cat); - idx = getstring (idx, in, &t); + 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) { @@ -3351,7 +2913,8 @@ do_include (idx, in) } 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); @@ -3425,7 +2988,7 @@ include_next_index () 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; } @@ -3441,6 +3004,9 @@ chartype_init () if (isalpha (x) || x == '_' || x == '$') chartype[x] |= FIRSTBIT; + if (mri && x == '.') + chartype[x] |= FIRSTBIT; + if (isdigit (x) || isalpha (x) || x == '_' || x == '$') chartype[x] |= NEXTBIT; @@ -3468,59 +3034,70 @@ chartype_init () #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 }, @@ -3568,6 +3145,30 @@ kinfo[] = { 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. */ @@ -3577,9 +3178,9 @@ process_pseudo_op (idx, line, acc) 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; @@ -3608,7 +3209,7 @@ process_pseudo_op (idx, line, acc) #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; } @@ -3622,6 +3223,16 @@ process_pseudo_op (idx, line, acc) 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 */ @@ -3656,6 +3267,7 @@ process_pseudo_op (idx, line, acc) { case K_ALTERNATE: alternate = 1; + macro_init (1, mri, 0, exp_get_abs); return 1; case K_AELSE: do_aelse (); @@ -3664,7 +3276,7 @@ process_pseudo_op (idx, line, acc) 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); @@ -3697,7 +3309,7 @@ process_pseudo_op (idx, line, acc) 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); @@ -3715,7 +3327,7 @@ process_pseudo_op (idx, line, acc) 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); @@ -3765,7 +3377,7 @@ process_pseudo_op (idx, line, acc) case K_IGNORED: return 1; case K_END: - do_end (); + do_end (line); return 1; case K_ASSIGNA: do_assigna (idx, line); @@ -3779,6 +3391,36 @@ process_pseudo_op (idx, line, acc) 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; } } } @@ -3787,6 +3429,29 @@ process_pseudo_op (idx, line, acc) +/* 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.*/ @@ -3796,27 +3461,19 @@ process_init () int i; for (i = 0; kinfo[i].name; i++) - { - sb label; - int j; - sb_new (&label); - sb_add_string (&label, kinfo[i].name); + add_keyword (kinfo[i].name, kinfo[i].code); - hash_add_to_int_table (&keyword_hash_table, &label, 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; @@ -3836,7 +3493,7 @@ char *string; 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; } @@ -3862,6 +3519,7 @@ static struct option long_options[] = { "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' }, @@ -3876,20 +3534,24 @@ show_usage (file, status) 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\ [-Ipath] add to include path list\n\ - [in-file]\n", program_name); + [in-file]\n")); + if (status == 0) + printf (_("Report bugs to %s\n"), REPORT_BUGS_TO); exit (status); } @@ -3897,7 +3559,7 @@ Usage: %s \n\ static void show_help () { - printf ("%s: Gnu Assembler Macro Preprocessor\n", + printf (_("%s: Gnu Assembler Macro Preprocessor\n"), program_name); show_usage (stdout, 0); } @@ -3914,20 +3576,22 @@ main (argc, argv) ifstack[0].on = 1; ifi = 0; - +#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES) + 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, "I:sdhavc:upo:D:", long_options, + while ((opt = getopt_long (argc, argv, "I:sdhavc:upo:D:M", long_options, (int *) NULL)) != EOF) { @@ -3942,6 +3606,7 @@ main (argc, argv) 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) @@ -3969,11 +3634,20 @@ main (argc, argv) 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: @@ -3984,12 +3658,15 @@ main (argc, argv) } } + 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); } @@ -4012,7 +3689,7 @@ main (argc, argv) } 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); } @@ -4022,3 +3699,18 @@ main (argc, argv) 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); +}