+
+/*---------------------------------------------.
+| Prepare the muscles for symbol definitions. |
+`---------------------------------------------*/
+
+static void
+prepare_symbol_definitions (void)
+{
+ int i;
+ for (i = 0; i < nsyms; ++i)
+ {
+ symbol *sym = symbols[i];
+ const char *key;
+ const char *value;
+
+#define SET_KEY(Entry) \
+ obstack_fgrow2 (&format_obstack, "symbol(%d, %s)", \
+ i, Entry); \
+ obstack_1grow (&format_obstack, 0); \
+ key = obstack_finish (&format_obstack);
+
+#define SET_KEY2(Entry, Suffix) \
+ obstack_fgrow3 (&format_obstack, "symbol(%d, %s_%s)", \
+ i, Entry, Suffix); \
+ obstack_1grow (&format_obstack, 0); \
+ key = obstack_finish (&format_obstack);
+
+ // Whether the symbol has an identifier.
+ value = symbol_id_get (sym);
+ SET_KEY("has_id");
+ MUSCLE_INSERT_INT (key, !!value);
+
+ // Its identifier.
+ SET_KEY("id");
+ MUSCLE_INSERT_STRING (key, value ? value : "");
+
+ // Its tag. Typically for documentation purpose.
+ SET_KEY("tag");
+ MUSCLE_INSERT_STRING (key, sym->tag);
+
+ SET_KEY("user_number");
+ MUSCLE_INSERT_INT (key, sym->user_token_number);
+
+ SET_KEY("is_token");
+ MUSCLE_INSERT_INT (key,
+ i < ntokens && sym != errtoken && sym != undeftoken);
+
+ SET_KEY("number");
+ MUSCLE_INSERT_INT (key, sym->number);
+
+ SET_KEY("has_type");
+ MUSCLE_INSERT_INT (key, !!sym->type_name);
+
+ SET_KEY("type");
+ MUSCLE_INSERT_STRING (key, sym->type_name ? sym->type_name : "");
+
+ {
+ int j;
+ for (j = 0; j < CODE_PROPS_SIZE; ++j)
+ {
+ /* "printer", not "%printer". */
+ char const *pname = code_props_type_string (j) + 1;
+ code_props const *p = symbol_code_props_get (sym, j);
+ SET_KEY2("has", pname);
+ MUSCLE_INSERT_INT (key, !!p->code);
+
+ if (p->code)
+ {
+ SET_KEY2(pname, "file");
+ MUSCLE_INSERT_STRING (key, p->location.start.file);
+
+ SET_KEY2(pname, "line");
+ MUSCLE_INSERT_INT (key, p->location.start.line);
+
+ SET_KEY(pname);
+ MUSCLE_INSERT_STRING_RAW (key, p->code);
+ }
+ }
+ }
+#undef SET_KEY2
+#undef SET_KEY
+ }
+}
+
+