+ if (*p == ',')
+ p++;
+ while (ISSPACE(*p))
+ p++;
+
+ if (*p == '\0')
+ return NULL;
+
+ start = p;
+
+ while (*p != ',' && *p != '\0')
+ p++;
+
+ *pstr = p;
+ return start;
+}
+
+/* Helper functions for define_predicate and define_special_predicate
+ processing. Shared between genrecog.c and genpreds.c. */
+
+static htab_t predicate_table;
+struct pred_data *first_predicate;
+static struct pred_data **last_predicate = &first_predicate;
+
+static hashval_t
+hash_struct_pred_data (const void *ptr)
+{
+ return htab_hash_string (((const struct pred_data *)ptr)->name);
+}
+
+static int
+eq_struct_pred_data (const void *a, const void *b)
+{
+ return !strcmp (((const struct pred_data *)a)->name,
+ ((const struct pred_data *)b)->name);
+}
+
+struct pred_data *
+lookup_predicate (const char *name)
+{
+ struct pred_data key;
+ key.name = name;
+ return htab_find (predicate_table, &key);
+}
+
+void
+add_predicate (struct pred_data *pred)
+{
+ void **slot = htab_find_slot (predicate_table, pred, INSERT);
+ if (*slot)
+ {
+ error ("duplicate predicate definition for '%s'", pred->name);
+ return;
+ }
+ *slot = pred;
+ *last_predicate = pred;
+ last_predicate = &pred->next;
+}
+
+/* This array gives the initial content of the predicate table. It
+ has entries for all predicates defined in recog.c. The back end
+ can define PREDICATE_CODES to give additional entries for the
+ table; this is considered an obsolete mechanism (use
+ define_predicate instead). */
+
+struct old_pred_table
+{
+ const char *name;
+ RTX_CODE codes[NUM_RTX_CODE];
+};
+
+static const struct old_pred_table old_preds[] = {
+ {"general_operand", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF,
+ LABEL_REF, SUBREG, REG, MEM }},
+ {"address_operand", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF,
+ LABEL_REF, SUBREG, REG, MEM,
+ PLUS, MINUS, MULT}},
+ {"register_operand", {SUBREG, REG}},
+ {"pmode_register_operand", {SUBREG, REG}},
+ {"scratch_operand", {SCRATCH, REG}},
+ {"immediate_operand", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF,
+ LABEL_REF}},
+ {"const_int_operand", {CONST_INT}},
+ {"const_double_operand", {CONST_INT, CONST_DOUBLE}},
+ {"nonimmediate_operand", {SUBREG, REG, MEM}},
+ {"nonmemory_operand", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF,
+ LABEL_REF, SUBREG, REG}},
+ {"push_operand", {MEM}},
+ {"pop_operand", {MEM}},
+ {"memory_operand", {SUBREG, MEM}},
+ {"indirect_operand", {SUBREG, MEM}},
+ {"comparison_operator", {EQ, NE, LE, LT, GE, GT, LEU, LTU, GEU, GTU,
+ UNORDERED, ORDERED, UNEQ, UNGE, UNGT, UNLE,
+ UNLT, LTGT}},
+#ifdef PREDICATE_CODES
+ PREDICATE_CODES
+#endif
+};
+#define NUM_KNOWN_OLD_PREDS ARRAY_SIZE (old_preds)
+
+/* This table gives the initial set of special predicates. It has
+ entries for all special predicates defined in recog.c. The back
+ end can define SPECIAL_MODE_PREDICATES to give additional entries
+ for the table; this is considered an obsolete mechanism (use
+ define_special_predicate instead). */
+static const char *const old_special_pred_table[] = {
+ "address_operand",
+ "pmode_register_operand",
+#ifdef SPECIAL_MODE_PREDICATES
+ SPECIAL_MODE_PREDICATES
+#endif
+};
+
+#define NUM_OLD_SPECIAL_MODE_PREDS ARRAY_SIZE (old_special_pred_table)
+
+/* Initialize the table of predicate definitions, starting with
+ the information we have on generic predicates, and the old-style
+ PREDICATE_CODES definitions. */
+
+static void
+init_predicate_table (void)
+{
+ size_t i, j;
+ struct pred_data *pred;
+
+ predicate_table = htab_create_alloc (37, hash_struct_pred_data,
+ eq_struct_pred_data, 0,
+ xcalloc, free);
+
+ for (i = 0; i < NUM_KNOWN_OLD_PREDS; i++)
+ {
+ pred = xcalloc (sizeof (struct pred_data), 1);
+ pred->name = old_preds[i].name;
+
+ for (j = 0; old_preds[i].codes[j] != 0; j++)
+ {
+ enum rtx_code code = old_preds[i].codes[j];
+
+ pred->codes[code] = true;
+ if (GET_RTX_CLASS (code) != RTX_CONST_OBJ)
+ pred->allows_non_const = true;
+ if (code != REG
+ && code != SUBREG
+ && code != MEM
+ && code != CONCAT
+ && code != PARALLEL
+ && code != STRICT_LOW_PART)
+ pred->allows_non_lvalue = true;
+ }
+ if (j == 1)
+ pred->singleton = old_preds[i].codes[0];
+
+ add_predicate (pred);
+ }
+
+ for (i = 0; i < NUM_OLD_SPECIAL_MODE_PREDS; i++)
+ {
+ pred = lookup_predicate (old_special_pred_table[i]);
+ if (!pred)
+ {
+ error ("old-style special predicate list refers "
+ "to unknown predicate '%s'", old_special_pred_table[i]);
+ continue;
+ }
+ pred->special = true;
+ }