static void as_internal_value_out_of_range (char * prefix, offsetT val, offsetT min, offsetT max, char * file, unsigned line, int bad) { const char * err; if (prefix == NULL) prefix = ""; #ifdef BFD_ASSEMBLER if ( val < HEX_MAX_THRESHOLD && min < HEX_MAX_THRESHOLD && max < HEX_MAX_THRESHOLD && val > HEX_MIN_THRESHOLD && min > HEX_MIN_THRESHOLD && max > HEX_MIN_THRESHOLD) #endif { /* xgettext:c-format */ err = _("%s out of range (%d is not between %d and %d)"); if (bad) as_bad_where (file, line, err, prefix, (int) val, (int) min, (int) max); else as_warn_where (file, line, err, prefix, (int) val, (int) min, (int) max); } #ifdef BFD_ASSEMBLER else { char val_buf [sizeof (val) * 3 + 2]; char min_buf [sizeof (val) * 3 + 2]; char max_buf [sizeof (val) * 3 + 2]; if (sizeof (val) > sizeof (bfd_vma)) abort (); sprintf_vma (val_buf, val); sprintf_vma (min_buf, min); sprintf_vma (max_buf, max); /* xgettext:c-format. */ err = _("%s out of range (0x%s is not between 0x%s and 0x%s)"); if (bad) as_bad_where (file, line, err, prefix, val_buf, min_buf, max_buf); else as_warn_where (file, line, err, prefix, val_buf, min_buf, max_buf); } #endif }
void s_else (int arg ATTRIBUTE_UNUSED) { if (current_cframe == NULL) { as_bad (_("\".else\" without matching \".if\"")); } else if (current_cframe->else_seen) { as_bad (_("duplicate \"else\"")); as_bad_where (current_cframe->else_file_line.file, current_cframe->else_file_line.line, _("here is the previous \"else\"")); as_bad_where (current_cframe->if_file_line.file, current_cframe->if_file_line.line, _("here is the previous \"if\"")); } else { as_where (¤t_cframe->else_file_line.file, ¤t_cframe->else_file_line.line); current_cframe->ignoring = current_cframe->dead_tree | !current_cframe->ignoring; if (LISTING_SKIP_COND () && (current_cframe->previous_cframe == NULL || ! current_cframe->previous_cframe->ignoring)) { if (! current_cframe->ignoring) listing_list (1); else listing_list (2); } current_cframe->else_seen = 1; } if (flag_mri) { while (! is_end_of_line[(unsigned char) *input_line_pointer]) ++input_line_pointer; } demand_empty_rest_of_line (); }
void cond_finish_check (int nest) { if (current_cframe != NULL && current_cframe->macro_nest >= nest) { if (nest >= 0) as_bad (_("end of macro inside conditional")); else as_bad (_("end of file inside conditional")); as_bad_where (current_cframe->if_file_line.file, current_cframe->if_file_line.line, _("here is the start of the unterminated conditional")); if (current_cframe->else_seen) as_bad_where (current_cframe->else_file_line.file, current_cframe->else_file_line.line, _("here is the \"else\" of the unterminated conditional")); } }
static void as_internal_value_out_of_range (char * prefix, offsetT val, offsetT min, offsetT max, char * file, unsigned line, int bad) { const char * err; if (prefix == NULL) prefix = ""; if (val >= min && val <= max) { addressT right = max & -max; if (max <= 1) abort (); /* xgettext:c-format */ err = _("%s out of domain (%d is not a multiple of %d)"); if (bad) as_bad_where (file, line, err, prefix, (int) val, (int) right); else as_warn_where (file, line, err, prefix, (int) val, (int) right); return; } if ( val < HEX_MAX_THRESHOLD && min < HEX_MAX_THRESHOLD && max < HEX_MAX_THRESHOLD && val > HEX_MIN_THRESHOLD && min > HEX_MIN_THRESHOLD && max > HEX_MIN_THRESHOLD) { /* xgettext:c-format */ err = _("%s out of range (%d is not between %d and %d)"); if (bad) as_bad_where (file, line, err, prefix, (int) val, (int) min, (int) max); else as_warn_where (file, line, err, prefix, (int) val, (int) min, (int) max); } else { char val_buf [sizeof (val) * 3 + 2]; char min_buf [sizeof (val) * 3 + 2]; char max_buf [sizeof (val) * 3 + 2]; if (sizeof (val) > sizeof (bfd_vma)) abort (); sprintf_vma (val_buf, (bfd_vma) val); sprintf_vma (min_buf, (bfd_vma) min); sprintf_vma (max_buf, (bfd_vma) max); /* xgettext:c-format. */ err = _("%s out of range (0x%s is not between 0x%s and 0x%s)"); if (bad) as_bad_where (file, line, err, prefix, val_buf, min_buf, max_buf); else as_warn_where (file, line, err, prefix, val_buf, min_buf, max_buf); } }
static const char * macro_expand_body (sb *in, sb *out, formal_entry *formals, struct hash_control *formal_hash, const macro_entry *macro) { sb t; int src = 0, inquote = 0, macro_line = 0; formal_entry *loclist = NULL; const char *err = NULL; sb_new (&t); while (src < in->len && !err) { if (in->ptr[src] == '&') { sb_reset (&t); if (macro_mri) { if (src + 1 < in->len && in->ptr[src + 1] == '&') src = sub_actual (src + 2, in, &t, formal_hash, '\'', out, 1); else sb_add_char (out, in->ptr[src++]); } else { /* FIXME: Why do we do this? */ /* At least in alternate mode this seems correct; without this one can't append a literal to a parameter. */ src = sub_actual (src + 1, in, &t, formal_hash, '&', out, 0); } } else if (in->ptr[src] == '\\') { src++; if (src < in->len && 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 (src < in->len) src++; else if (!macro) err = _("missing `)'"); else as_bad_where (macro->file, macro->line + macro_line, _("missing `)'")); } else if (src < in->len && in->ptr[src] == '@') { /* Sub in the macro invocation number. */ char buffer[10]; src++; sprintf (buffer, "%d", macro_number); sb_add_string (out, buffer); } else if (src < in->len && 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 if (macro_mri && src < in->len && ISALNUM (in->ptr[src])) { int ind; formal_entry *f; if (ISDIGIT (in->ptr[src])) ind = in->ptr[src] - '0'; else if (ISUPPER (in->ptr[src])) ind = in->ptr[src] - 'A' + 10; else ind = in->ptr[src] - 'a' + 10; ++src; for (f = formals; f != NULL; f = f->next) { if (f->index == ind - 1) { if (f->actual.len != 0) sb_add_sb (out, &f->actual); else sb_add_sb (out, &f->def); break; } } } else { sb_reset (&t); src = sub_actual (src, in, &t, formal_hash, '\'', out, 0); } } else if ((macro_alternate || macro_mri) && is_name_beginner (in->ptr[src]) && (! inquote || ! macro_strip_at || (src > 0 && in->ptr[src - 1] == '@'))) { if (! macro || src + 5 >= in->len || strncasecmp (in->ptr + src, "LOCAL", 5) != 0 || ! ISWHITE (in->ptr[src + 5])) { sb_reset (&t); src = sub_actual (src, in, &t, formal_hash, (macro_strip_at && inquote) ? '@' : '\'', out, 1); } else { src = sb_skip_white (src + 5, in); while (in->ptr[src] != '\n') { const char *name; formal_entry *f = new_formal (); src = get_token (src, in, &f->name); name = sb_terminate (&f->name); if (! hash_find (formal_hash, name)) { static int loccnt; char buf[20]; f->index = LOCAL_INDEX; f->next = loclist; loclist = f; sprintf (buf, IS_ELF ? ".LL%04x" : "LL%04x", ++loccnt); sb_add_string (&f->actual, buf); err = hash_jam (formal_hash, name, f); if (err != NULL) break; } else { as_bad_where (macro->file, macro->line + macro_line, _("`%s' was already used as parameter (or another local) name"), name); del_formal (f); } src = sb_skip_comma (src, in); } } } else if (in->ptr[src] == '"' || (macro_mri && in->ptr[src] == '\'')) { inquote = !inquote; sb_add_char (out, in->ptr[src++]); } else if (in->ptr[src] == '@' && macro_strip_at) { ++src; if (src < in->len && in->ptr[src] == '@') { sb_add_char (out, '@'); ++src; } } else if (macro_mri && in->ptr[src] == '=' && src + 1 < in->len && in->ptr[src + 1] == '=') { formal_entry *ptr; sb_reset (&t); src = get_token (src + 2, in, &t); ptr = (formal_entry *) hash_find (formal_hash, sb_terminate (&t)); if (ptr == NULL) { /* FIXME: We should really return a warning string here, but we can't, because the == might be in the MRI comment field, and, since the nature of the MRI comment field depends upon the exact instruction being used, we don't have enough information here to figure out whether it is or not. Instead, we leave the == in place, which should cause a syntax error if it is not in a comment. */ sb_add_char (out, '='); sb_add_char (out, '='); sb_add_sb (out, &t); } else { if (ptr->actual.len) { sb_add_string (out, "-1"); } else { sb_add_char (out, '0'); } } } else { if (in->ptr[src] == '\n') ++macro_line; sb_add_char (out, in->ptr[src++]); } } sb_kill (&t); while (loclist != NULL) { formal_entry *f; f = loclist->next; /* Setting the value to NULL effectively deletes the entry. We avoid calling hash_delete because it doesn't reclaim memory. */ hash_jam (formal_hash, sb_terminate (&loclist->name), NULL); del_formal (loclist); loclist = f; } return err; }
static int do_formals (macro_entry *macro, int idx, sb *in) { formal_entry **p = ¯o->formals; const char *name; idx = sb_skip_white (idx, in); while (idx < in->len) { formal_entry *formal = new_formal (); int cidx; idx = get_token (idx, in, &formal->name); if (formal->name.len == 0) { if (macro->formal_count) --idx; break; } idx = sb_skip_white (idx, in); /* This is a formal. */ name = sb_terminate (&formal->name); if (! macro_mri && idx < in->len && in->ptr[idx] == ':' && (! is_name_beginner (':') || idx + 1 >= in->len || ! is_part_of_name (in->ptr[idx + 1]))) { /* Got a qualifier. */ sb qual; sb_new (&qual); idx = get_token (sb_skip_white (idx + 1, in), in, &qual); sb_terminate (&qual); if (qual.len == 0) as_bad_where (macro->file, macro->line, _("Missing parameter qualifier for `%s' in macro `%s'"), name, macro->name); else if (strcmp (qual.ptr, "req") == 0) formal->type = FORMAL_REQUIRED; else if (strcmp (qual.ptr, "vararg") == 0) formal->type = FORMAL_VARARG; else as_bad_where (macro->file, macro->line, _("`%s' is not a valid parameter qualifier for `%s' in macro `%s'"), qual.ptr, name, macro->name); sb_kill (&qual); idx = sb_skip_white (idx, in); } if (idx < in->len && in->ptr[idx] == '=') { /* Got a default. */ idx = get_any_string (idx + 1, in, &formal->def); idx = sb_skip_white (idx, in); if (formal->type == FORMAL_REQUIRED) { sb_reset (&formal->def); as_warn_where (macro->file, macro->line, _("Pointless default value for required parameter `%s' in macro `%s'"), name, macro->name); } } /* Add to macro's hash table. */ if (! hash_find (macro->formal_hash, name)) hash_jam (macro->formal_hash, name, formal); else as_bad_where (macro->file, macro->line, _("A parameter named `%s' already exists for macro `%s'"), name, macro->name); formal->index = macro->formal_count++; *p = formal; p = &formal->next; if (formal->type == FORMAL_VARARG) break; cidx = idx; idx = sb_skip_comma (idx, in); if (idx != cidx && idx >= in->len) { idx = cidx; break; } } if (macro_mri) { formal_entry *formal = new_formal (); /* Add a special NARG formal, which macro_expand will set to the number of arguments. */ /* The same MRI assemblers which treat '@' characters also use the name $NARG. At least until we find an exception. */ if (macro_strip_at) name = "$NARG"; else name = "NARG"; sb_add_string (&formal->name, name); /* Add to macro's hash table. */ if (hash_find (macro->formal_hash, name)) as_bad_where (macro->file, macro->line, _("Reserved word `%s' used as parameter in macro `%s'"), name, macro->name); hash_jam (macro->formal_hash, name, formal); formal->index = NARG_INDEX; *p = formal; } return idx; }
void s_elseif (int arg) { if (current_cframe == NULL) { as_bad (_("\".elseif\" without matching \".if\"")); } else if (current_cframe->else_seen) { as_bad (_("\".elseif\" after \".else\"")); as_bad_where (current_cframe->else_file_line.file, current_cframe->else_file_line.line, _("here is the previous \"else\"")); as_bad_where (current_cframe->if_file_line.file, current_cframe->if_file_line.line, _("here is the previous \"if\"")); } else { as_where (¤t_cframe->else_file_line.file, ¤t_cframe->else_file_line.line); current_cframe->dead_tree |= !current_cframe->ignoring; current_cframe->ignoring = current_cframe->dead_tree; } if (current_cframe == NULL || current_cframe->ignoring) { while (! is_end_of_line[(unsigned char) *input_line_pointer]) ++input_line_pointer; if (current_cframe == NULL) return; } else { expressionS operand; int t; /* Leading whitespace is part of operand. */ SKIP_WHITESPACE (); expression (&operand); if (operand.X_op != O_constant) as_bad (_("non-constant expression in \".elseif\" statement")); switch ((operatorT) arg) { case O_eq: t = operand.X_add_number == 0; break; case O_ne: t = operand.X_add_number != 0; break; case O_lt: t = operand.X_add_number < 0; break; case O_le: t = operand.X_add_number <= 0; break; case O_ge: t = operand.X_add_number >= 0; break; case O_gt: t = operand.X_add_number > 0; break; default: abort (); return; } current_cframe->ignoring = current_cframe->dead_tree || ! t; } if (LISTING_SKIP_COND () && (current_cframe->previous_cframe == NULL || ! current_cframe->previous_cframe->ignoring)) { if (! current_cframe->ignoring) listing_list (1); else listing_list (2); } demand_empty_rest_of_line (); }