static void dot_cfi_sections (int ignored ATTRIBUTE_UNUSED) { int sections = 0; SKIP_WHITESPACE (); if (is_name_beginner (*input_line_pointer)) while (1) { char *name, c; name = input_line_pointer; c = get_symbol_end (); if (strncmp (name, ".eh_frame", sizeof ".eh_frame") == 0 && name[9] != '_') sections |= CFI_EMIT_eh_frame; else if (strncmp (name, ".debug_frame", sizeof ".debug_frame") == 0) sections |= CFI_EMIT_debug_frame; #ifdef tc_cfi_section_name else if (strcmp (name, tc_cfi_section_name) == 0) sections |= CFI_EMIT_target; #endif else { *input_line_pointer = c; input_line_pointer = name; break; } *input_line_pointer = c; SKIP_WHITESPACE (); if (*input_line_pointer == ',') { name = input_line_pointer++; SKIP_WHITESPACE (); if (!is_name_beginner (*input_line_pointer)) { input_line_pointer = name; break; } } else if (is_name_beginner (*input_line_pointer)) break; } demand_empty_rest_of_line (); cfi_sections = sections; }
void s_ifdef (int test_defined) { /* Points to name of symbol. */ char *name; /* Points to symbol. */ symbolS *symbolP; struct conditional_frame cframe; char c; /* Leading whitespace is part of operand. */ SKIP_WHITESPACE (); name = input_line_pointer; if (!is_name_beginner (*name)) { as_bad (_("invalid identifier for \".ifdef\"")); obstack_1grow (&cond_obstack, 0); ignore_rest_of_line (); return; } c = get_symbol_end (); symbolP = symbol_find (name); *input_line_pointer = c; initialize_cframe (&cframe); if (cframe.dead_tree) cframe.ignoring = 1; else { int is_defined; /* Use the same definition of 'defined' as .equiv so that a symbol which has been referenced but not yet given a value/address is considered to be undefined. */ is_defined = symbolP != NULL && S_IS_DEFINED (symbolP) && S_GET_SEGMENT (symbolP) != reg_section; cframe.ignoring = ! (test_defined ^ is_defined); } current_cframe = ((struct conditional_frame *) obstack_copy (&cond_obstack, &cframe, sizeof (cframe))); if (LISTING_SKIP_COND () && cframe.ignoring && (cframe.previous_cframe == NULL || ! cframe.previous_cframe->ignoring)) listing_list (2); demand_empty_rest_of_line (); }
static unsigned cfi_parse_reg (void) { int regno; expressionS exp; #ifdef tc_regname_to_dw2regnum SKIP_WHITESPACE (); if (is_name_beginner (*input_line_pointer) || (*input_line_pointer == '%' && is_name_beginner (*++input_line_pointer))) { char *name, c; name = input_line_pointer; c = get_symbol_end (); if ((regno = tc_regname_to_dw2regnum (name)) < 0) { as_bad (_("bad register expression")); regno = 0; } *input_line_pointer = c; return regno; } #endif expression_and_evaluate (&exp); switch (exp.X_op) { case O_register: case O_constant: regno = exp.X_add_number; break; default: as_bad (_("bad register expression")); regno = 0; break; } return regno; }
static void obj_coff_val (int ignore ATTRIBUTE_UNUSED) { if (def_symbol_in_progress == NULL) { as_warn (_(".val pseudo-op used outside of .def/.endef ignored.")); demand_empty_rest_of_line (); return; } if (is_name_beginner (*input_line_pointer)) { char *symbol_name = input_line_pointer; char name_end = get_symbol_end (); #ifdef tc_canonicalize_symbol_name symbol_name = tc_canonicalize_symbol_name (symbol_name); #endif if (streq (symbol_name, ".")) { /* If the .val is != from the .def (e.g. statics). */ symbol_set_frag (def_symbol_in_progress, frag_now); S_SET_VALUE (def_symbol_in_progress, (valueT) frag_now_fix ()); } else if (! streq (S_GET_NAME (def_symbol_in_progress), symbol_name)) { expressionS exp; exp.X_op = O_symbol; exp.X_add_symbol = symbol_find_or_make (symbol_name); exp.X_op_symbol = NULL; exp.X_add_number = 0; symbol_set_value_expression (def_symbol_in_progress, &exp); /* If the segment is undefined when the forward reference is resolved, then copy the segment id from the forward symbol. */ SF_SET_GET_SEGMENT (def_symbol_in_progress); /* FIXME: gcc can generate address expressions here in unusual cases (search for "obscure" in sdbout.c). We just ignore the offset here, thus generating incorrect debugging information. We ignore the rest of the line just below. */ } /* Otherwise, it is the name of a non debug symbol and its value will be calculated later. */ *input_line_pointer = name_end; } else { S_SET_VALUE (def_symbol_in_progress, get_absolute_expression ()); } demand_empty_rest_of_line (); }
static void tc_parse_to_dw2regnum (expressionS *exp) { # ifdef tc_regname_to_dw2regnum SKIP_WHITESPACE (); if (is_name_beginner (*input_line_pointer) || (*input_line_pointer == '%' && is_name_beginner (*++input_line_pointer))) { char *name, c; name = input_line_pointer; c = get_symbol_end (); exp->X_op = O_constant; exp->X_add_number = tc_regname_to_dw2regnum (name); *input_line_pointer = c; } else # endif expression_and_evaluate (exp); }
int check_macro (const char *line, sb *expand, const char **error, macro_entry **info) { const char *s; char *copy, *cs; macro_entry *macro; sb line_sb; if (! is_name_beginner (*line) && (! macro_mri || *line != '.')) return 0; s = line + 1; while (is_part_of_name (*s)) ++s; if (is_name_ender (*s)) ++s; copy = (char *) alloca (s - line + 1); memcpy (copy, line, s - line); copy[s - line] = '\0'; for (cs = copy; *cs != '\0'; cs++) *cs = TOLOWER (*cs); macro = (macro_entry *) hash_find (macro_hash, copy); if (macro == NULL) return 0; /* Wrap the line up in an sb. */ sb_new (&line_sb); while (*s != '\0' && *s != '\n' && *s != '\r') sb_add_char (&line_sb, *s++); sb_new (expand); *error = macro_expand (0, &line_sb, macro, expand); sb_kill (&line_sb); /* Export the macro information if requested. */ if (info) *info = macro; return 1; }
static void dot_cfi_startproc (int ignored ATTRIBUTE_UNUSED) { int simple = 0; if (frchain_now->frch_cfi_data != NULL) { as_bad (_("previous CFI entry not closed (missing .cfi_endproc)")); ignore_rest_of_line (); return; } cfi_new_fde (symbol_temp_new_now ()); SKIP_WHITESPACE (); if (is_name_beginner (*input_line_pointer)) { char *name, c; name = input_line_pointer; c = get_symbol_end (); if (strcmp (name, "simple") == 0) { simple = 1; *input_line_pointer = c; } else input_line_pointer = name; } demand_empty_rest_of_line (); frchain_now->frch_cfi_data->cur_cfa_offset = 0; if (!simple) tc_cfi_frame_initial_instructions (); if ((cfi_sections & CFI_EMIT_target) != 0) tc_cfi_startproc (); }
static int get_token (int idx, sb *in, sb *name) { if (idx < in->len && is_name_beginner (in->ptr[idx])) { sb_add_char (name, in->ptr[idx++]); while (idx < in->len && is_part_of_name (in->ptr[idx])) { sb_add_char (name, in->ptr[idx++]); } if (idx < in->len && is_name_ender (in->ptr[idx])) { sb_add_char (name, in->ptr[idx++]); } } /* Ignore trailing &. */ if (macro_alternate && idx < in->len && in->ptr[idx] == '&') idx++; return idx; }
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; }
int buffer_and_nest (const char *from, const char *to, sb *ptr, int (*get_line) (sb *)) { int from_len; int to_len = strlen (to); int depth = 1; int line_start = ptr->len; int more = get_line (ptr); if (to_len == 4 && strcasecmp(to, "ENDR") == 0) { from = NULL; from_len = 0; } else from_len = strlen (from); while (more) { /* Try to find the first pseudo op on the line. */ int i = line_start; /* With normal syntax we can suck what we want till we get to the dot. With the alternate, labels have to start in the first column, since we can't tell what's a label and what's a pseudoop. */ if (! LABELS_WITHOUT_COLONS) { /* Skip leading whitespace. */ while (i < ptr->len && ISWHITE (ptr->ptr[i])) i++; } for (;;) { /* Skip over a label, if any. */ if (i >= ptr->len || ! is_name_beginner (ptr->ptr[i])) break; i++; while (i < ptr->len && is_part_of_name (ptr->ptr[i])) i++; if (i < ptr->len && is_name_ender (ptr->ptr[i])) i++; if (LABELS_WITHOUT_COLONS) break; /* Skip whitespace. */ while (i < ptr->len && ISWHITE (ptr->ptr[i])) i++; /* Check for the colon. */ if (i >= ptr->len || ptr->ptr[i] != ':') { i = line_start; break; } i++; line_start = i; } /* Skip trailing whitespace. */ while (i < ptr->len && ISWHITE (ptr->ptr[i])) i++; if (i < ptr->len && (ptr->ptr[i] == '.' || NO_PSEUDO_DOT || macro_mri)) { if (! flag_m68k_mri && ptr->ptr[i] == '.') i++; if (from == NULL && strncasecmp (ptr->ptr + i, "IRPC", from_len = 4) != 0 && strncasecmp (ptr->ptr + i, "IRP", from_len = 3) != 0 && strncasecmp (ptr->ptr + i, "IREPC", from_len = 5) != 0 && strncasecmp (ptr->ptr + i, "IREP", from_len = 4) != 0 && strncasecmp (ptr->ptr + i, "REPT", from_len = 4) != 0 && strncasecmp (ptr->ptr + i, "REP", from_len = 3) != 0) from_len = 0; if ((from != NULL ? strncasecmp (ptr->ptr + i, from, from_len) == 0 : from_len > 0) && (ptr->len == (i + from_len) || ! (is_part_of_name (ptr->ptr[i + from_len]) || is_name_ender (ptr->ptr[i + from_len])))) depth++; if (strncasecmp (ptr->ptr + i, to, to_len) == 0 && (ptr->len == (i + to_len) || ! (is_part_of_name (ptr->ptr[i + to_len]) || is_name_ender (ptr->ptr[i + to_len])))) { depth--; if (depth == 0) { /* Reset the string to not include the ending rune. */ ptr->len = line_start; break; } } } /* Add the original end-of-line char to the end and keep running. */ sb_add_char (ptr, more); line_start = ptr->len; more = get_line (ptr); } /* Return 1 on success, 0 on unexpected EOF. */ return depth == 0; }