return true;
}
+static void
+expand_template (const struct template *tmpl,
+ const struct template_instance *inst,
+ char *dst, const char *src, int lineno)
+{
+ while (*src)
+ {
+ const char *ident = tmpl->name, *end;
+ const struct template_param *param;
+ const struct template_arg *arg;
+
+ if ((*dst = *src++) != '<')
+ {
+ ++dst;
+ continue;
+ }
+ while (ISSPACE(*src))
+ ++src;
+ while (*ident && *src == *ident)
+ ++src, ++ident;
+ while (ISSPACE(*src))
+ ++src;
+ if (*src != ':' || *ident != '\0')
+ {
+ memcpy (++dst, tmpl->name, ident - tmpl->name);
+ dst += ident - tmpl->name;
+ continue;
+ }
+ while (ISSPACE(*++src))
+ ;
+
+ end = src;
+ while (*end != '\0' && !ISSPACE(*end) && *end != '>')
+ ++end;
+
+ for (param = tmpl->params, arg = inst->args; param;
+ param = param->next, arg = arg->next)
+ {
+ if (end - src == strlen (param->name)
+ && !memcmp (src, param->name, end - src))
+ {
+ src = end;
+ break;
+ }
+ }
+
+ if (param == NULL)
+ fail ("template '%s' has no parameter '%.*s'\n",
+ tmpl->name, (int)(end - src), src);
+
+ while (ISSPACE(*src))
+ ++src;
+ if (*src != '>')
+ fail ("%s: %d: missing '>'\n", filename, lineno);
+
+ memcpy(dst, arg->val, strlen(arg->val));
+ dst += strlen(arg->val);
+ ++src;
+ }
+
+ *dst = '\0';
+}
+
static unsigned int
expand_templates (char *name, const char *str, htab_t opcode_hash_table,
struct opcode_hash_entry ***opcode_array_p, int lineno)
for (inst = tmpl->instances; inst; inst = inst->next)
{
- char *name2 = xmalloc(strlen(name) + strlen(inst->name) + strlen(ptr2) + 1);
+ char *name2 = xmalloc(strlen(name) + strlen(inst->name)
+ + 2 * strlen(ptr2) + 1);
char *str2 = xmalloc(2 * strlen(str));
- const char *src;
- strcpy (name2, name);
- strcat (name2, inst->name);
- strcat (name2, ptr2);
+ ptr1 = stpcpy (name2, name);
+ ptr1 = stpcpy (ptr1, inst->name);
- for (ptr1 = str2, src = str; *src; )
- {
- const char *ident = tmpl->name, *end;
- const struct template_param *param;
- const struct template_arg *arg;
-
- if ((*ptr1 = *src++) != '<')
- {
- ++ptr1;
- continue;
- }
- while (ISSPACE(*src))
- ++src;
- while (*ident && *src == *ident)
- ++src, ++ident;
- while (ISSPACE(*src))
- ++src;
- if (*src != ':' || *ident != '\0')
- {
- memcpy (++ptr1, tmpl->name, ident - tmpl->name);
- ptr1 += ident - tmpl->name;
- continue;
- }
- while (ISSPACE(*++src))
- ;
-
- end = src;
- while (*end != '\0' && !ISSPACE(*end) && *end != '>')
- ++end;
-
- for (param = tmpl->params, arg = inst->args; param;
- param = param->next, arg = arg->next)
- {
- if (end - src == strlen (param->name)
- && !memcmp (src, param->name, end - src))
- {
- src = end;
- break;
- }
- }
-
- if (param == NULL)
- fail ("template '%s' has no parameter '%.*s'\n",
- tmpl->name, (int)(end - src), src);
-
- while (ISSPACE(*src))
- ++src;
- if (*src != '>')
- fail ("%s: %d: missing '>'\n", filename, lineno);
-
- memcpy(ptr1, arg->val, strlen(arg->val));
- ptr1 += strlen(arg->val);
- ++src;
- }
+ /* Expand this template in trailing portion of mnemonic. */
+ expand_template (tmpl, inst, ptr1, ptr2, lineno);
- *ptr1 = '\0';
+ /* Expand this template in attributes and operands. */
+ expand_template (tmpl, inst, str2, str, lineno);
+ /* Expand further templates, if any. */
expand_templates (name2, str2, opcode_hash_table, opcode_array_p,
lineno);