예제 #1
0
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;
}
예제 #2
0
static char *
extract_word (char *from, char *to, int limit)
{
  char *op_end;
  int size = 0;

  /* Drop leading whitespace.  */
  from = skip_space (from);
  *to = 0;

  /* Find the op code end.  */
  for (op_end = from; *op_end != 0 && is_part_of_name (*op_end);)
    {
      to[size++] = *op_end++;
      if (size + 1 >= limit)
	break;
    }

  to[size] = 0;
  return op_end;
}
예제 #3
0
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;
}
예제 #4
0
static int
do_formals (macro_entry *macro, int idx, sb *in)
{
  formal_entry **p = &macro->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;
}
예제 #5
0
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;
}