X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gas%2Fgasp.c;h=aae4cbe7dbc6c22913b465112f8f49c1c589515a;hb=02ad0c056d0890b76fd0f3c83787ea852d083a83;hp=83ccc557e7b2b1881ce1bdcea38000253b433d5a;hpb=2db90a6320f3661031f1b917854615942eeeeffd;p=deliverable%2Fbinutils-gdb.git diff --git a/gas/gasp.c b/gas/gasp.c index 83ccc557e7..aae4cbe7db 100644 --- a/gas/gasp.c +++ b/gas/gasp.c @@ -1,5 +1,5 @@ /* 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, sac@cygnus.com @@ -17,8 +17,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, 675 Mass Ave, Cambridge, MA 02139, 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. */ /* @@ -37,6 +38,7 @@ suitable for gas to consume. -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 <..> @@ -46,16 +48,34 @@ suitable for gas to consume. */ +#include "config.h" #include +#include #include #include -#include "host.h" +#ifdef HAVE_STDLIB_H +#include +#endif + +#ifdef NEED_MALLOC_DECLARATION +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 */ @@ -67,6 +87,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 */ @@ -75,72 +96,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. */ @@ -580,8 +397,12 @@ hash_new_table (size, ptr) int size; hash_table *ptr; { + int i; ptr->size = size; ptr->table = (hash_entry **) xmalloc (size * (sizeof (hash_entry *))); + /* Fill with null-pointer, not zero-bit-pattern. */ + for (i = 0; i < size; i++) + ptr->table[i] = 0; } /* calculate and return the hash value of the sb at key. */ @@ -655,7 +476,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; @@ -710,10 +531,10 @@ hash_lookup (tab, key) expression precedence: ( ) unary + - ~ -* / -+ - -& -| ~ + * / + + - + & + | ~ */ @@ -723,13 +544,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)); } } @@ -771,9 +592,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; @@ -789,7 +608,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); } @@ -808,13 +627,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); @@ -854,7 +673,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; @@ -891,7 +710,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; @@ -923,7 +742,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) @@ -1061,7 +880,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; @@ -1082,8 +901,8 @@ hash_table vars; /* hash table for eq variables */ #define in_comment ';' -#if 1 -void +#if 0 +static void strip_comments (out) sb *out; { @@ -1102,7 +921,7 @@ strip_comments (out) /* push back character ch so that it can be read again. */ -void +static void unget (ch) int ch; { @@ -1128,7 +947,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; @@ -1151,7 +970,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++; } } @@ -1206,7 +1025,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'; @@ -1261,7 +1080,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++; @@ -1290,7 +1109,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; @@ -1313,7 +1146,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; } @@ -1333,7 +1166,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 @@ -1349,6 +1182,18 @@ change_base (idx, in, out) idx++; } } + else if (in->ptr[idx] == '"' || in->ptr[idx] == '\'') + { + char tchar = in->ptr[idx]; + /* copy entire names through quickly */ + sb_add_char (out, in->ptr[idx]); + idx++; + while (idx < in->len && in->ptr[idx] != tchar) + { + sb_add_char (out, in->ptr[idx]); + idx++; + } + } else { /* nothing special, just pass it through */ @@ -1361,9 +1206,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 */ @@ -1413,7 +1261,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)); } } @@ -1422,9 +1270,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] == '.') @@ -1449,7 +1297,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++; @@ -1459,8 +1307,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 @@ -1481,7 +1329,7 @@ do_data (idx, in, size) int size; { int opsize = 4; - char *opname; + char *opname = ".yikes!"; sb acc; sb_new (&acc); @@ -1540,7 +1388,7 @@ do_data (idx, in, size) } } sb_kill (&acc); - sb_print_at (idx, in); + sb_print_at (outfile, idx, in); fprintf (outfile, "\n"); } @@ -1557,38 +1405,52 @@ 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; + + 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] */ -void +static void do_res (idx, in, type) int idx; sb *in; - char type; + int type; { int size = 4; int count = 0; @@ -1599,7 +1461,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++; @@ -1611,7 +1473,7 @@ do_res (idx, in, type) /* .export */ -void +static void do_export (in) sb *in; { @@ -1620,7 +1482,7 @@ do_export (in) /* .print [list] [nolist] */ -void +static void do_print (idx, in) int idx; sb *in; @@ -1628,12 +1490,12 @@ do_print (idx, in) idx = sb_skip_white (idx, in); while (idx < in->len) { - if (strncmp (in->ptr + idx, "LIST", 4) == 0) + if (strncasecmp (in->ptr + idx, "LIST", 4) == 0) { fprintf (outfile, ".list\n"); idx += 4; } - else if (strncmp (in->ptr + idx, "NOLIST", 6) == 0) + else if (strncasecmp (in->ptr + idx, "NOLIST", 6) == 0) { fprintf (outfile, ".nolist\n"); idx += 6; @@ -1643,7 +1505,7 @@ do_print (idx, in) } /* .head */ -void +static void do_heading (idx, in) int idx; sb *in; @@ -1657,14 +1519,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; @@ -1676,16 +1538,16 @@ do_form (idx, in) while (idx < in->len) { - if (strncmp (in->ptr + idx, "LIN=", 4) == 0) + 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 (strncmp (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++; @@ -1694,39 +1556,55 @@ do_form (idx, in) } -int -get_any_string (idx, in, out) + +/* Fetch string from the input stream, + rules: + 'Bxyx -> return 'Bxyza + % -> return string of decimal value of x + "" -> return string + xyx -> return xyz +*/ +static int +get_any_string (idx, in, out, expand, pretend_quoted) int idx; sb *in; sb *out; + int expand; + int pretend_quoted; { sb_reset (out); idx = sb_skip_white (idx, in); - if (idx < in->len) { - if (in->ptr[idx] == '%' - && alternate) + if (in->len > 2 && in->ptr[idx+1] == '\'' && ISBASE (in->ptr[idx])) + { + while (!ISSEP (in->ptr[idx])) + sb_add_char (out, in->ptr[idx++]); + } + else if (in->ptr[idx] == '%' + && alternate + && expand) { 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); - sprintf(buf, "\"%d\"", val); + sprintf(buf, "%d", val); sb_add_string (out, buf); } - else if (in->ptr[idx] == '"' - || in->ptr[idx] == '<' - || (alternate && in->ptr[idx] == '\'')) + else if (in->ptr[idx] == '"' + || in->ptr[idx] == '<' + || (alternate && in->ptr[idx] == '\'')) { - if (alternate) + if (alternate && expand) { /* Keep the quotes */ sb_add_char (out, '\"'); + idx = getstring (idx, in, out); sb_add_char (out, '\"'); @@ -1740,6 +1618,7 @@ get_any_string (idx, in, out) while (idx < in->len && (in->ptr[idx] == '"' || in->ptr[idx] == '\'' + || pretend_quoted || !ISSEP (in->ptr[idx]))) { if (in->ptr[idx] == '"' @@ -1750,12 +1629,14 @@ get_any_string (idx, in, out) while (idx < in->len && in->ptr[idx] != tchar) sb_add_char (out, in->ptr[idx++]); + if (idx == in->len) + return idx; } sb_add_char (out, in->ptr[idx++]); - } } } + return idx; } @@ -1763,14 +1644,14 @@ get_any_string (idx, in, out) /* 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; } @@ -1778,21 +1659,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; @@ -1837,9 +1718,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 { @@ -1877,9 +1758,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); @@ -1904,7 +1785,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; @@ -1914,37 +1795,50 @@ 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); } else if (idx + 3 < in->len && in->ptr[idx] == '.' - && in->ptr[idx + 1] == 'L' - && in->ptr[idx + 2] == 'E' - && in->ptr[idx + 3] == 'N') + && toupper ((unsigned char) in->ptr[idx + 1]) == 'L' + && toupper ((unsigned char) in->ptr[idx + 2]) == 'E' + && toupper ((unsigned char) in->ptr[idx + 3]) == 'N') idx = dolen (idx + 4, in, buf); else if (idx + 6 < in->len && in->ptr[idx] == '.' - && in->ptr[idx + 1] == 'I' - && in->ptr[idx + 2] == 'N' - && in->ptr[idx + 3] == 'S' - && in->ptr[idx + 4] == 'T' - && in->ptr[idx + 5] == 'R') + && toupper ((unsigned char) in->ptr[idx + 1]) == 'I' + && toupper ((unsigned char) in->ptr[idx + 2]) == 'N' + && toupper ((unsigned char) in->ptr[idx + 3]) == 'S' + && toupper ((unsigned char) in->ptr[idx + 4]) == 'T' + && toupper ((unsigned char) in->ptr[idx + 5]) == 'R') idx = doinstr (idx + 6, in, buf); else if (idx + 7 < in->len && in->ptr[idx] == '.' - && in->ptr[idx + 1] == 'S' - && in->ptr[idx + 2] == 'U' - && in->ptr[idx + 3] == 'B' - && in->ptr[idx + 4] == 'S' - && in->ptr[idx + 5] == 'T' - && in->ptr[idx + 6] == 'R') + && toupper ((unsigned char) in->ptr[idx + 1]) == 'S' + && toupper ((unsigned char) in->ptr[idx + 2]) == 'U' + && toupper ((unsigned char) in->ptr[idx + 3]) == 'B' + && toupper ((unsigned char) in->ptr[idx + 4]) == 'S' + && toupper ((unsigned char) in->ptr[idx + 5]) == 'T' + && toupper ((unsigned char) in->ptr[idx + 6]) == 'R') idx = dosubstr (idx + 7, in, buf); else if (ISFIRSTCHAR (in->ptr[idx])) { @@ -1986,7 +1880,7 @@ get_and_process (idx, in, out) { sb t; sb_new (&t); - idx = get_any_string (idx, in, &t); + idx = get_any_string (idx, in, &t, 1, 0); process_assigns (0, &t, out); sb_kill (&t); return idx; @@ -2018,23 +1912,54 @@ process_file () 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)) @@ -2083,8 +2008,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"))); } @@ -2104,7 +2029,7 @@ free_old_entry (ptr) /* name: .ASSIGNA */ -void +static void do_assigna (idx, in) int idx; sb *in; @@ -2114,11 +2039,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 { @@ -2132,7 +2057,7 @@ do_assigna (idx, in) /* name: .ASSIGNC */ -void +static void do_assignc (idx, in) int idx; sb *in; @@ -2143,7 +2068,7 @@ do_assignc (idx, in) if (!label.len) { - ERROR ((stderr, ".ASSIGNS without label.\n")); + ERROR ((stderr, _(".ASSIGNS without label.\n"))); } else { @@ -2166,9 +2091,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++; @@ -2204,7 +2135,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 { @@ -2236,31 +2167,40 @@ condass_lookup_name (inbuf, idx, out, warn) #define GT 6 #define NEVER 7 -int +static int whatcond (idx, in, val) int idx; sb *in; int *val; { int cond; - char *p; + idx = sb_skip_white (idx, in); - p = in->ptr + idx; - if (p[0] == 'E' && p[1] == 'Q') - cond = EQ; - else if (p[0] == 'N' && p[1] == 'E') - cond = NE; - else if (p[0] == 'L' && p[1] == 'T') - cond = LT; - else if (p[0] == 'L' && p[1] == 'E') - cond = LE; - else if (p[0] == 'G' && p[1] == 'T') - cond = GT; - else if (p[0] == 'G' && p[1] == 'E') - cond = GE; - else - { - ERROR ((stderr, "Comparison operator must be one of EQ, NE, LT, LE, GT or GE.\n")); + cond = NEVER; + if (idx + 1 < in->len) + { + char *p; + char a, b; + + p = in->ptr + idx; + a = toupper ((unsigned char) p[0]); + b = toupper ((unsigned char) p[1]); + if (a == 'E' && b == 'Q') + cond = EQ; + else if (a == 'N' && b == 'E') + cond = NE; + else if (a == 'L' && b == 'T') + cond = LT; + else if (a == 'L' && b == 'E') + cond = LE; + else if (a == 'G' && b == 'T') + cond = GT; + else if (a == 'G' && b == 'E') + cond = GE; + } + if (cond == NEVER) + { + 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); @@ -2268,7 +2208,7 @@ whatcond (idx, in, val) return idx; } -int +static int istrue (idx, in) int idx; sb *in; @@ -2294,11 +2234,11 @@ 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 - res = cond == EQ && same; + res = (cond != EQ) ^ same; } else /* This is a numeric expression */ @@ -2306,19 +2246,22 @@ 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: + res = 42; + break; case EQ: res = vala == valb; break; @@ -2358,10 +2301,10 @@ do_aif (idx, in) { if (ifi >= IFNESTING) { - FATAL ((stderr, "AIF nesting unreasonable.\n")); + FATAL ((stderr, _("AIF nesting unreasonable.\n"))); } ifi++; - ifstack[ifi].on = istrue (idx, in); + ifstack[ifi].on = ifstack[ifi-1].on ? istrue (idx, in) : 0; ifstack[ifi].hadelse = 0; } @@ -2370,10 +2313,10 @@ do_aif (idx, in) static void do_aelse () { - ifstack[ifi].on = !ifstack[ifi].on; + 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; } @@ -2389,7 +2332,7 @@ do_aendi () } else { - ERROR ((stderr, "AENDI without AIF.\n")); + ERROR ((stderr, _("AENDI without AIF.\n"))); } } @@ -2399,93 +2342,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 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 */ + FATAL ((stderr, _("IF nesting unreasonable.\n"))); + } - /* Skip leading whitespace */ - while (i < ptr->len - && ISWHITE (ptr->ptr[i])) - i++; + 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; + } - /* Skip over a label */ - while (i < ptr->len - && ISNEXTCHAR (ptr->ptr[i])) - i++; + ifi++; + ifstack[ifi].on = ifstack[ifi-1].on ? res: 0; + ifstack[ifi].hadelse = 0; +} - /* And a colon */ - if (i < ptr->len - && ptr->ptr[i] == ':') - i++; +/* Get a string for the MRI IFC or IFNC pseudo-ops. */ - } - /* 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 (strncmp (ptr->ptr + i, from, from_len) == 0) - depth++; - if (strncmp (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 */ @@ -2496,18 +2480,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 @@ -2545,7 +2530,7 @@ do_awhile (idx, in) static void do_aendw () { - ERROR ((stderr, "AENDW without a AENDW.\n")); + ERROR ((stderr, _("AENDW without a AENDW.\n"))); } @@ -2578,17 +2563,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 @@ -2606,10 +2599,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); @@ -2624,73 +2623,33 @@ 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); - } - } - - { - /* 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 @@ -2698,357 +2657,52 @@ do_local (idx, line) 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++]); - } - } - 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]) - && in->ptr[scan] != '=') - scan++; - if (scan < in->len && 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); - } - } - 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); - 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 @@ -3066,7 +2720,7 @@ getstring (idx, in, acc) { if (in->ptr[idx] == '<') { - if (alternate) + if (alternate || mri) { int nest = 0; idx++; @@ -3091,12 +2745,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++; } } @@ -3135,7 +2789,7 @@ void do_sdata (idx, in, type) int idx; sb *in; - char type; + int type; { int nc = 0; int pidx = -1; @@ -3150,12 +2804,12 @@ do_sdata (idx, in, type) idx = sb_skip_white (idx, in); while (!eol (idx, in)) { - pidx = idx = get_any_string (idx, in, &acc); + pidx = idx = get_any_string (idx, in, &acc, 0, 1); if (type == 'c') { 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; @@ -3183,7 +2837,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++; @@ -3204,10 +2858,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; } @@ -3219,23 +2873,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 (%d).\n", isp)); + FATAL ((stderr, _("Unreasonable include depth (%ld).\n"), (long) isp)); sp++; sp->handle = newone; @@ -3257,14 +2911,41 @@ do_include (idx, in) 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) { - FATAL ((stderr, "Can't open include file `%s'.\n", text)); + 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) + { + if (! new_file (sb_name (&t))) + FATAL ((stderr, _("Can't open include file `%s'.\n"), sb_name (&t))); + } + sb_kill (&cat); sb_kill (&t); } @@ -3336,7 +3017,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; } @@ -3352,6 +3033,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; @@ -3359,6 +3043,12 @@ chartype_init () || x == '"' || x == '<' || x == '>' || x == ')' || x == '(') chartype[x] |= SEPBIT; + if (x == 'b' || x == 'B' + || x == 'q' || x == 'Q' + || x == 'h' || x == 'H' + || x == 'd' || x == 'D') + chartype [x] |= BASEBIT; + if (x == ' ' || x == '\t') chartype[x] |= WHITEBIT; @@ -3373,59 +3063,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 }, @@ -3473,6 +3174,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. */ @@ -3482,9 +3207,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; @@ -3513,7 +3238,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; } @@ -3527,6 +3252,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 */ @@ -3543,6 +3278,9 @@ process_pseudo_op (idx, line, acc) { switch (ptr->value.i) { + case K_AIF: + do_aif (idx, line); + break; case K_AELSE: do_aelse (); break; @@ -3558,6 +3296,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 (); @@ -3566,7 +3305,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); @@ -3599,7 +3338,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); @@ -3617,7 +3356,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); @@ -3667,7 +3406,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); @@ -3681,6 +3420,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; } } } @@ -3689,6 +3458,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.*/ @@ -3698,27 +3490,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); - - 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); + add_keyword (kinfo[i].name, 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; @@ -3738,7 +3522,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; } @@ -3759,10 +3543,12 @@ char *program_name; 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' }, @@ -3777,19 +3563,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\ - [in-file]\n", program_name); + [-Ipath] add to include path list\n\ + [in-file]\n")); + if (status == 0) + printf (_("\nReport bugs to bug-gnu-utils@gnu.org\n")); exit (status); } @@ -3797,7 +3588,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); } @@ -3814,20 +3605,22 @@ main (argc, argv) 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) { @@ -3839,6 +3632,19 @@ main (argc, argv) 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; @@ -3857,11 +3663,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: @@ -3872,12 +3687,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); } @@ -3900,7 +3718,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); } @@ -3910,3 +3728,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); +}